From: <Saved by Windows Internet Explorer 7>
Subject: Setting up Rails on Windows XP
Date: Sun, 4 May 2008 11:02:25 +0200
MIME-Version: 1.0
Content-Type: multipart/related;
	type="text/html";
	boundary="----=_NextPart_000_0009_01C8ADD6.55A08950"
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3198

This is a multi-part message in MIME format.

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: text/html;
	charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/articles/19-setting-up-rails-on-windows-xp

=EF=BB=BF<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" =
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML xmlns=3D"http://www.w3.org/1999/xhtml"><HEAD><TITLE>Setting up =
Rails on Windows XP</TITLE>
<META http-equiv=3DContent-Type content=3D"text/html; charset=3DUTF-8">
<META=20
content=3D"ruby on rails, web applications, model view controller, =
prototype, agile"=20
name=3Dkeywords>
<META=20
content=3D"An information resource for web application developers, =
combining original articles with an extensive set of annotated, =
organized links to the web's best resources."=20
name=3Ddescription>
<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/prototype.js?1209768151=
"=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/effects.js?1209768151" =

type=3Dtext/javascript></SCRIPT>

<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/dragdrop.js?1209768151"=
=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/controls.js?1209768151"=
=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT=20
src=3D"http://www.buildingwebapps.com/javascripts/application.js?12097681=
51"=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/column.js?1209768151"=20
type=3Dtext/javascript></SCRIPT>
<!--[if lt IE 7]>=0A=
		<script =
src=3D"http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" =
type=3D"text/javascript"></script>=0A=
		<![endif]--><LINK=20
media=3Dscreen=20
href=3D"http://www.buildingwebapps.com/stylesheets/main.css?1209768151"=20
type=3Dtext/css rel=3Dstylesheet><LINK media=3Dscreen=20
href=3D"http://www.buildingwebapps.com/stylesheets/append.css?1209768151"=
=20
type=3Dtext/css rel=3Dstylesheet><LINK media=3Dscreen=20
href=3D"http://www.buildingwebapps.com/stylesheets/treeview-menu.css?1209=
768151"=20
type=3Dtext/css rel=3Dstylesheet><LINK media=3Dscreen=20
href=3D"http://www.buildingwebapps.com/stylesheets/stars.css?1209768151" =

type=3Dtext/css rel=3Dstylesheet>
<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/yahoo-min.js?1209768151=
"=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/event-min.js?1209768151=
"=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT=20
src=3D"http://www.buildingwebapps.com/javascripts/treeview-min.js?1209768=
151"=20
type=3Dtext/javascript></SCRIPT>

<SCRIPT =
src=3D"http://www.buildingwebapps.com/javascripts/stars.js?1209768151"=20
type=3Dtext/javascript></SCRIPT>
<LINK media=3Dprint=20
href=3D"http://www.buildingwebapps.com/stylesheets/print.css?1209768151" =

type=3Dtext/css rel=3Dstylesheet><LINK title=3DATOM=20
href=3D"http://feeds.feedburner.com/buildingwebappsarticles"=20
type=3Dapplication/atom+xml rel=3Dalternate>
<META content=3D"MSHTML 6.00.6000.16640" name=3DGENERATOR></HEAD>
<BODY><!-- ClickTale Top part -->
<SCRIPT=20
type=3Dtext/javascript>=0A=
  var WRInitTime=3D(new Date()).getTime();=0A=
  </SCRIPT>
<!-- ClickTale end of Top part -->
<SCRIPT type=3Dtext/javascript>=0A=
  var gaJsHost =3D (("https:" =3D=3D document.location.protocol) ? =
"https://ssl." : "http://www.");=0A=
  document.write("\<script src=3D'" + gaJsHost + =
"google-analytics.com/ga.js' type=3D'text/javascript'>\<\/script>" );=0A=
  </SCRIPT>

<SCRIPT type=3Dtext/javascript>=0A=
  var pageTracker =3D _gat._getTracker("UA-3052557-1");=0A=
  pageTracker._initData();=0A=
  pageTracker._trackPageview();=0A=
  </SCRIPT>

<DIV id=3DpageWrapper>
<DIV id=3Dheader>
<DIV class=3Dclearfix id=3DtopHead>
<DIV id=3Dinline_search_box>
<FORM action=3D/search method=3Dget><INPUT id=3Dsearch_text =
style=3D"MARGIN-TOP: -5px"=20
size=3D16 name=3Dsearch_text> <INPUT=20
style=3D"VERTICAL-ALIGN: bottom; PADDING-TOP: 5px" type=3Dimage=20
src=3D"http://www.buildingwebapps.com/images/search.gif?1209768151"> =
</FORM></DIV>
<DIV class=3DleftHead><A href=3D"http://www.buildingwebapps.com/"><IMG =
height=3D70=20
alt=3D"BuildingWebapps Logo"=20
src=3D"http://www.buildingwebapps.com/images/bwa_beta_logo.gif"=20
width=3D259></A></DIV><!-- Utility Nav -->
<DIV class=3DrightHead>
<DIV class=3DrightHeadSpacer>
<UL id=3DnavList>
  <LI><A class=3DgreyLink =
href=3D"http://www.buildingwebapps.com/course">Online=20
  Course</A> |=20
  <LI><A class=3DgreyLink =
href=3D"http://blog.buildingwebapps.com/">Blog</A> |=20
  <LI><A class=3DgreyLink =
href=3D"http://www.buildingwebapps.com/contact">Contact=20
  Us</A> |=20
  <LI><A class=3DgreyLink =
href=3D"http://www.buildingwebapps.com/page/about">About=20
  Us</A> |=20
  <LI><A class=3DgreyLink =
href=3D"http://www.buildingwebapps.com/feeds">Feeds</A>=20
  </LI></UL></DIV></DIV><!-- End Utility Nav --></DIV>
<DIV class=3Dclearfix id=3DbotHead>
<DIV class=3DleftHead style=3D"MARGIN-TOP: 0px"><SPAN =
class=3Dtagline>Resources for=20
Web Application Developers</SPAN></DIV>
<DIV class=3DrightHead><!-- Main Nav -->
<DIV id=3Darticles>
<DIV id=3Dnav>
<UL>
  <LI id=3Dnav-home><A href=3D"http://www.buildingwebapps.com/">Home</A> =
</LI>
  <LI><A =
href=3D"http://www.buildingwebapps.com/topic/5-ruby-on-rails">Ruby on=20
  Rails</A> </LI>
  <LI><A =
href=3D"http://www.buildingwebapps.com/topic/3-servers">Servers</A> =
</LI>
  <LI><A =
href=3D"http://www.buildingwebapps.com/topic/18-user-interface">User=20
  Interface</A> </LI>
  <LI><A=20
  =
href=3D"http://www.buildingwebapps.com/topic/4-development">Development</=
A>=20
</LI>
  <LI><A =
href=3D"http://www.buildingwebapps.com/topic/95-business">Business</A>=20
  </LI></UL></DIV></DIV><!-- End Main Nav --></DIV></DIV>
<DIV class=3Dclearfix id=3DsubNavContainer>
<DIV id=3DsubNav>
<UL></UL></DIV></DIV></DIV>
<DIV class=3Dclearfix id=3Dcontent>
<DIV id=3DleftCol>
<DIV class=3Dclearfix id=3DsubColContainer>
<DIV id=3DsubColBody>
<DIV id=3DsubColBodyContent><BR><BR>
<DIV id=3Darticle_body>
<P style=3D"MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><A=20
href=3D"http://www.buildingwebapps.com/articles/home?category=3D4-develop=
ment">More=20
articles about Development</A></P>
<P style=3D"MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><A=20
href=3D"http://www.buildingwebapps.com/articles/home?category=3D5-ruby-on=
-rails">More=20
articles about Ruby on Rails</A></P>
<H1 style=3D"PADDING-TOP: 8px">Setting up Rails on Windows XP</H1>
<H2>By Christopher Haupt</H2>
<P>Published April 23, 2008&nbsp;&nbsp;|&nbsp;&nbsp; <SPAN =
class=3Dnoprint=20
href=3D"#comments" <a>4 comments</A></SPAN> <SPAN style=3D"PADDING-LEFT: =
15px">
<SCRIPT type=3Dtext/javascript>addthis_pub  =3D 'mzslater';</SCRIPT>
<A onmouseover=3D"return addthis_open(this, '', '[URL]', '[TITLE]')"=20
onclick=3D"return addthis_sendto()" onmouseout=3Daddthis_close()=20
href=3D"http://www.addthis.com/bookmark.php"><IMG class=3Dnoprint=20
style=3D"VERTICAL-ALIGN: -15%" height=3D16 alt=3D""=20
src=3D"http://s9.addthis.com/button1-share.gif" width=3D125 border=3D0> =
</A>
<SCRIPT src=3D"http://s7.addthis.com/js/152/addthis_widget.js"=20
type=3Dtext/javascript>=0A=
       </SCRIPT>
</SPAN></P>
<DIV class=3Dnoprint style=3D"FLOAT: right; MARGIN: 0px 0px 0px 20px; =
WIDTH: 200px">
<H2 style=3D"MARGIN-BOTTOM: 0px">Related Topics</H2>
<UL style=3D"MARGIN-TOP: 0px">
  <LI><A =
href=3D"http://www.buildingwebapps.com/topic/5-ruby-on-rails">Ruby on=20
  Rails</A> &gt; <A =
href=3D"http://www.buildingwebapps.com/topic/148-how-to">How=20
  To...</A> &gt; <A=20
  =
href=3D"http://www.buildingwebapps.com/topic/244-configuration">Configura=
tion</A></LI></UL>
<H2 style=3D"MARGIN-BOTTOM: 0px">Related Articles</H2>
<UL style=3D"PADDING-TOP: 0px">
  <LI style=3D"LINE-HEIGHT: 130%"><A=20
  =
href=3D"http://www.buildingwebapps.com/articles/20-setting-up-rails-on-wi=
ndows-vista">Setting=20
  up Rails on Windows Vista</A>=20
  <LI style=3D"LINE-HEIGHT: 130%"><A=20
  =
href=3D"http://www.buildingwebapps.com/articles/17-setting-up-rails-on-le=
opard-mac">Setting=20
  up Rails on Leopard (Mac OS X 10.5)</A>=20
  <LI style=3D"LINE-HEIGHT: 130%"><A=20
  =
href=3D"http://www.buildingwebapps.com/articles/8-using-ssl-in-rails-appl=
ications">Using=20
  SSL in Rails Applications</A>=20
  <LI style=3D"LINE-HEIGHT: 130%"><A=20
  =
href=3D"http://www.buildingwebapps.com/articles/18-setting-up-rails-on-ti=
ger-mac">Setting=20
  up Rails on Tiger (Mac OS X 10.4)</A>=20
  <LI style=3D"LINE-HEIGHT: 130%"><A=20
  =
href=3D"http://www.buildingwebapps.com/articles/13-can-rails-scale-absolu=
tely">Can=20
  Rails Scale? Absolutely!</A>=20
  <LI style=3D"LINE-HEIGHT: 130%"><A=20
  =
href=3D"http://www.buildingwebapps.com/articles/23-selling-friends-scalin=
g-a-high-traffic-rails">Selling=20
  Friends: Scaling a High-Traffic Rails Application</A> </LI></UL></DIV>
<DIV>
<P>This guide walks you through setup instructions for preparing a =
Windows XP=20
development machine to be used for general Ruby on Rails coding. This =
baseline=20
setup is what we use for our <A=20
href=3D"http://www.buildingwebapps.com/course">LearningRails online =
course</A> and=20
the <A href=3D"http://www.buildingwebapps.com/seminar">in-person =
seminars</A> we=20
offer.</P>
<P>You will end up with a development machine with the following =
baseline=20
components:</P>
<OL>
  <LI>Ruby and all basic Ruby utilities=20
  <LI>Ruby Gems package manager=20
  <LI>Subversion client=20
  <LI>MySQL database client utilities and server=20
  <LI>Gems for Ruby on Rails, Capistrano, Mongrel, Mongrel Cluster, and =
MySQL=20
  <LI><SPAN class=3Dcaps>SSH</SPAN> Terminal Program=20
  <LI>Programmer=E2=80=99s editor or <SPAN class=3Dcaps>IDE</SPAN> =
</LI></OL>
<P>Note: In the command sequences we illustrate here, command line =
prompts are=20
shown as <CODE>C:\&gt;</CODE>.</P>
<H2>Prerequisites</H2>
<P>This guide assumes you have a Windows computer running the current =
Windows XP=20
operating system with up-to-date service patches applied (SP2 or =
higher). It=20
also assumes you have not set up alternate Ruby on Rails tools prior to =
running=20
through this guide. If you have, then small adjustments may be required =
as you=20
walk through the following instructions.</P>
<P>You will need to have access to an Internet connection to complete =
various=20
download steps.</P>
<P>You will need to have administrator access to your computer to =
complete this=20
guide. Some of the Windows installers may ask you for your password.</P>
<H2>The Recipe</H2>
<P>Follow this recipe in sequence. If you have previously installed a =
particular=20
component, you can usually skip the associated step.</P>
<H3>Ruby and Ruby Utilities (irb, ri, rdoc)</H3>
<P>The <A =
href=3D"http://rubyforge.org/projects/rubyinstaller/">One-Click Ruby=20
Installer</A> does a lot of work for you by installing Ruby, Ruby Gems =
Package=20
Manager, Rake, all of the other standard Ruby tools, and even the open =
source=20
SciTE programmer=E2=80=99s editor. Additionally, the installer =
configures the command=20
line interface path information, so the Ruby tools are ready to use in =
the=20
Command Prompt program.</P>
<P>Download the latest installer (1.8.6 r26 as of this writing) and =
double click=20
on it to get started.</P>
<P><IMG alt=3D""=20
src=3D"http://www.buildingwebapps.com/assets/installwinxp_1click.jpg"></P=
>
<P>Select all of the default settings and let the installer complete its =
work.=20
Once done, open a <CODE>Command Prompt</CODE> (aka <SPAN =
class=3Dcaps>DOS</SPAN>=20
Command Line) window by selecting the Start menu, then the Run=E2=80=A6 =
menu item, and=20
then typing <CODE>cmd</CODE> and pressing return.</P>
<P>You can check that Ruby is installed by typing the command:</P><PRE>  =
  C:\&gt; ruby -v
    ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]
</PRE>
<P>You should seem similar responses. If you get an unrecognized command =
error,=20
try closing your Command Prompt window and opening another one.</P>
<H3>Ruby Gems Package Manager</H3>
<P>You next need to install the latest version of <CODE>gem</CODE>.</P>
<P>Check the version that gets installed:</P><PRE>    C:\&gt; gem -v
    0.9.4
</PRE>
<P>You need 1.0.1 or newer. If you have an older version, you can update =
with=20
the command line: <CODE>gem update --system</CODE>.</P>
<H3>Installing a Subversion client</H3>
<P>Subversion will be used to access your source code repository during=20
development and deployments. You will need a current version of the =
Subversion=20
command line client and you can use the <A=20
href=3D"http://subversion.tigris.org/servlets/ProjectDocumentList?folderI=
D=3D91">official=20
Windows installers on subversion.tigris.org</A>.</P>
<P>Download the latest =E2=80=9CWindows installer with the basic win32 =
binaries=E2=80=9D option=20
on the site. Double click the setup program and select the default =
options.</P>
<P><IMG alt=3D""=20
src=3D"http://www.buildingwebapps.com/assets/installwinxp_svn.jpg"></P>
<P>Once the installer is done, open a new Command Prompt window and =
check the=20
installation:</P><PRE>    C:\&gt; svn --version
    svn, version 1.4.6 (r28521)
       compiled Dec 20 2007, 16:33:06
    ...
</PRE>
<H3>Installing MySQL via the Offical MySQL Installer</H3>
<P>You will be installing MySQL via the official <A=20
href=3D"http://dev.mysql.com/downloads/mysql/5.0.html#win32">Windows=20
Essentials</A> installer from MySQL.com. This installer handles all of =
the setup=20
steps for you. After downloading the community edition (open source) =
Windows=20
Essentials setup program, double click it to start:</P>
<P><IMG alt=3D""=20
src=3D"http://www.buildingwebapps.com/assets/installwinxp_mysql_1.jpg"></=
P>
<P>Select the default (=E2=80=9CTypical=E2=80=9D) settings and location =
and let the program=20
install itself. After it completes, a few ads will be shown, then a =
final dialog=20
allowing you to configure the MySQL server. Make sure the check-box is =
selected=20
and press =E2=80=9CFinish=E2=80=9D.</P>
<P><IMG alt=3D""=20
src=3D"http://www.buildingwebapps.com/assets/installwinxp_mysql_2.jpg"></=
P>
<P>The =E2=80=9CMySQL Server Instance Configuration Wizard=E2=80=9D will =
run next. Choose the=20
=E2=80=9CDetailed Configuration=E2=80=9D option and select all of the =
default choices. Doing so=20
will configure the database to be running with settings best designed =
for a=20
developer=E2=80=99s computer. When you get to the dialog offering the =
=E2=80=9CInclude Bin=20
Directory in Windows <SPAN class=3Dcaps>PATH</SPAN>=E2=80=9D option, we =
suggest you select=20
it. If you don=E2=80=99t choose this option, you will need to manually =
set up your path=20
so the =E2=80=9CCommand Prompt=E2=80=9D program has easy access to MySQL =
client programs.</P>
<P><IMG alt=3D""=20
src=3D"http://www.buildingwebapps.com/assets/installwinxp_mysql_3.jpg"></=
P>
<P>You will also be presented with a dialog to set a root password. If =
you are=20
going to be working locally and aren=E2=80=99t worried about security, =
you can deselect=20
=E2=80=9CModify Security Settings=E2=80=9D and have a blank root =
password. We strongly suggest=20
you set a password to be safe.</P>
<P>You can confirm that MySQL is running by trying to fire it up in the =
Command=20
Prompt program:</P><PRE>    C:\&gt; mysql -p -u root
    Enter password: ****
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 5.0.51a-community-nt MySQL Community Edition (GPL)

    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

    mysql&gt; exit
</PRE>
<P>When you reboot your computer, MySQL will start automatically in the=20
future.</P>
<H3>Gems</H3>
<P>While the One-Click Ruby installer added some common Windows oriented =
gems=20
for you, you still need the Ruby on Rails gems and the gems used in the=20
LearningRails course. Install them with the command:</P><PRE>    C:\&gt; =
gem install rails capistrano mongrel mongrel_cluster
</PRE>
<P>All installed gems (including Ruby on Rails and its dependencies, =
Capistrano,=20
Mongrel, and Mongrel_Cluster) will get installed at their latest =
versions.</P>
<P>The MySQL adapter gem needs to be installed next.</P><PRE>    C:\&gt; =
gem install mysql
</PRE>
<P>Once the command completes, you should be all set with the baseline =
gems you=20
will need for the LearningRails courses.</P>
<H3><SPAN class=3Dcaps>SSH</SPAN> Terminal Program</H3>
<P>In deployment environments where your production or other remote =
servers are=20
running a Unix-derived operating system, you will want to log in to =
those=20
machines using the <SPAN class=3Dcaps>SSH</SPAN> protocol. A good =
Windows <SPAN=20
class=3Dcaps>SSH</SPAN> terminal program is <A=20
href=3D"http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">=
PuTTY</A>.=20
Download the complete Windows installer and double click to let it =
run.</P>
<P><IMG alt=3D""=20
src=3D"http://www.buildingwebapps.com/assets/installwinxp_putty.jpg"></P>=

<P>You can select all of the default options. Once the installer =
finishes, you=20
are ready to login to your remote machines.</P>
<H3>Code Editing Tools</H3>
<P>While you can get by with using a plain text editor like Notepad you =
will=20
have much higher productivity if you use a programming editor that is =
highly=20
tuned to Ruby on Rails development. The One-Click Ruby installer =
automatically=20
installed the SciTE programmer=E2=80=99s editor. SciTE is ok for basic =
tasks with one or=20
two files, but we recommend trying some of the other programs below.</P>
<P>We use the commercial <A href=3D"http://macromates.com/">TextMate</A> =

programmer=E2=80=99s editor for much of our day to day work on the =
Macintosh. TextMate=20
is highly extensible through a collection of community supplied =
=E2=80=9Cbundles=E2=80=9D. There=20
is a Windows =E2=80=9Clook-a-like/port=E2=80=9D called the <A =
href=3D"http://e-texteditor.com/">E=20
Text Editor</A> that looks promising and includes much of the =
functionality=20
found on the Mac. Even better, it is supposed to be compatible with =
TextMate=20
bundles, so as functionality improves for one platform, it should become =

available on the other. There is a trial version available if you want =
to test=20
it out.</P>
<P>There are a variety of good open source or free programmer editors =
available=20
too. On the open source side you can find ports of vim and emacs, both =
of which=20
have add-ons to create a full featured Ruby and Rails development tool =
set. <A=20
href=3D"http://www.jedit.org/">jEdit</A> is a very extensible open =
source editor=20
written in Java that has a decent Ruby programming plugin set.</P>
<P>Whatever editor you choose, be certain that it provides easy =
navigation among=20
a large number of open files. Working with Rails applications generally =
involves=20
dealing with a lot of small files, and that process needs to be =
efficient.</P>
<P>If you prefer an all-in-one tool, you should look at one of several=20
integrated development environments that exist for Ruby. We use <A=20
href=3D"http://www.netbeans.org/">Netbeans</A> in our LearningRails =
courses, but=20
you should check out the numerous <A=20
href=3D"http://www.buildingwebapps.com/topic/26-integrated-development-en=
vironments-ides">other=20
options listed at BuildingWebApps.com</A>.</P>
<SCRIPT type=3Dtext/javascript>addthis_pub  =3D 'mzslater';</SCRIPT>
<A onmouseover=3D"return addthis_open(this, '', '[URL]', '[TITLE]')"=20
onclick=3D"return addthis_sendto()" onmouseout=3Daddthis_close()=20
href=3D"http://www.addthis.com/bookmark.php"><IMG class=3Dnoprint =
height=3D16 alt=3D""=20
src=3D"http://s9.addthis.com/button1-share.gif" width=3D125 border=3D0> =
</A>
<SCRIPT src=3D"http://s7.addthis.com/js/152/addthis_widget.js"=20
type=3Dtext/javascript>=0A=
        </SCRIPT>

<HR>

<DIV class=3Dnoprint><A name=3Dcomments></A>
<DIV id=3Dcomment_intro>
<DIV class=3Ddbtext>
<H2>Add your comment on this article</H2></DIV></DIV>
<DIV id=3Dnew_comment_div>
<DIV id=3Dcomment_errors></DIV>
<FORM id=3Dcomment_form=20
onsubmit=3D"new =
Ajax.Request('/articles/19-setting-up-rails-on-windows-xp/comments', =
{asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); =
return false;"=20
action=3D/articles/19-setting-up-rails-on-windows-xp/comments =
method=3Dpost>
<P style=3D"MARGIN-BOTTOM: 3px"><LABEL>Your Name</LABEL><BR><INPUT =
id=3Dcomment_name=20
style=3D"WIDTH: 300px" size=3D29 name=3Dcomment[name]></P>
<P><LABEL>Email (required, not published)</LABEL><BR><INPUT =
id=3Dcomment_email=20
style=3D"WIDTH: 300px" size=3D29 name=3Dcomment[email]></P>
<DIV id=3Dform_email>
<P style=3D"MARGIN-BOTTOM: 3px"><LABEL>Email (again)</LABEL><BR><INPUT =
id=3Demail2=20
style=3D"WIDTH: 180px" size=3D29 name=3Demail2></P></DIV>
<P style=3D"MARGIN-BOTTOM: 3px"><LABEL>Subject</LABEL><BR><INPUT=20
id=3Dcomment_subject style=3D"WIDTH: 440px" size=3D29 =
name=3Dcomment[subject]></P>
<P style=3D"MARGIN-BOTTOM: 5px"><LABEL>Comment</LABEL><BR><TEXTAREA =
id=3Dcomment_body style=3D"WIDTH: 440px" name=3Dcomment[body] rows=3D4 =
cols=3D100></TEXTAREA></P>
<P><INPUT type=3Dimage=20
src=3D"http://www.buildingwebapps.com/images/submit.gif?1209768151"></P><=
/FORM></DIV>
<DIV id=3Dcomment_result></DIV></DIV>
<DIV class=3Ddbtext>
<H2>Reader comments on this article</H2></DIV>
<DIV id=3Dcomment_list>
<DIV class=3Dmini_comment>
<P>From: Christopher =
Haupt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date:=20
04/29/08 10:10 AM</P>
<P>Subject: RE: Setting up when you don't have an Internet =
Connection</P>
<P>[Elopez] Yes, you can install on a disconnected machine. If your =
machines are=20
the same architecture, you can grab your local gem cache=20
(C:\ruby\lib\ruby\gems\1.8\cache on my machine). You can also download =
gems=20
manually from places like RubyForge.org, or use the command "gem fetch". =
There=20
are more complicated things you can do (including setting up local gem=20
repositories and gem servers, but we'll skip that). Once you have the =
gem files=20
local and transfered to your offline machine, move into that directory =
and use=20
"gem install gemname --local" where gemname is the gem(s) you wish to =
install.=20
</P></DIV>
<DIV class=3Dmini_comment>
<P>From: Elopez&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date: 04/29/08 =
05:05=20
AM</P>
<P>Subject: setting up when you dont have internet connection</P>
<P>Hi, Great article thank you guys for putting time to do this series =
that I am=20
sure will help a lot of new rails programmers like me. I want to ask you =
is=20
there a way to download the gems and install them in another machine =
(laptop)=20
that does have internet connection.</P></DIV>
<DIV class=3Dmini_comment>
<P>From: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date: 04/20/08 04:16 =
PM</P>
<P>Subject: great article!</P>
<P>This is a great article and helped me a lot!</P></DIV>
<DIV class=3Dmini_comment>
<P>From: AnotherDave&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date: =
04/07/08=20
01:13 PM</P>
<P>Subject: Setting up Rails on Windows XP</P>
<P>Following your instructions to the letter, and using the same =
versions of the=20
same software, will not deliver a workable Rails system. The first try, =
the=20
installer puked on XP's wonderful "Program Files" directory path. I =
don't=20
suppose it gave you any trouble at all. Second try, the installed =
programs=20
failed to configure themselves for my spaceless c:\programs directory. I =
suppose=20
I'll get this all sorted out someday, but then I supposed that about ten =
other=20
installation tutorials would work, too. </P></DIV></DIV></DIV></DIV>
<SCRIPT=20
src=3D"http://feeds.feedburner.com/~s/buildingwebappsarticles?i=3Dhttp://=
www.buildingwebapps.com//articles/19-setting-up-rails-on-windows-xp"=20
type=3Dtext/javascript charset=3Dutf-8></SCRIPT>
</DIV></DIV>
<DIV id=3DsubColFoot></DIV></DIV></DIV>
<DIV id=3DrightCol>
<DIV id=3DrightColContainerFullCol style=3D"CLEAR: right">
<DIV id=3DrightColBody>
<DIV id=3DrightColBodyContent style=3D"MARGIN-RIGHT: -3px">
<H3 class=3DsidebarHead>Join our List</H3>
<P>And we'll let you know when we post major new site updates.</P>
<DIV id=3Dsignup style=3D"MARGIN-TOP: -5px">
<FORM action=3Dhttp://www.aweber.com/scripts/addlead.pl method=3Dpost>
<DIV style=3D"MARGIN-BOTTOM: 10px">
<P style=3D"MARGIN-BOTTOM: 0px"><LABEL>Email Address</LABEL></P>
<DIV><INPUT type=3Dhidden value=3D1837544126 name=3Dmeta_web_form_id> =
<INPUT=20
type=3Dhidden name=3Dmeta_split_id> <INPUT type=3Dhidden =
value=3Dbuildingwebapps=20
name=3Dunit> <INPUT id=3Dredirect_3aefc928682958e72efcd31161d901cf =
type=3Dhidden=20
value=3Dhttp://www.buildingwebapps.com/signedup name=3Dredirect> <INPUT =
type=3Dhidden=20
value=3Dhttp://www.buildingwebapps.com/signedup_duplicate=20
name=3Dmeta_redirect_onlist> <INPUT type=3Dhidden =
name=3Dmeta_adtracking> <INPUT=20
type=3Dhidden value=3D1 name=3Dmeta_message> <INPUT type=3Dhidden =
value=3Dfrom=20
name=3Dmeta_required> <INPUT type=3Dhidden value=3D0 =
name=3Dmeta_forward_vars> <INPUT=20
style=3D"VERTICAL-ALIGN: top; WIDTH: 102px" size=3D25 =
name=3Dfrom></TD></TR> <INPUT=20
type=3Dimage =
src=3D"http://www.buildingwebapps.com/images/submit.gif?1209768151"=20
disable_with=3D"Please wait..."> </DIV></DIV></FORM>
<DIV style=3D"MARGIN-TOP: -13px; FONT-SIZE: 11px">
<DIV class=3Ddbtext>
<P>We=E2=80=99ll never share your email address with anyone=20
else.</P></DIV></DIV></DIV></DIV></DIV>
<DIV id=3DrightColFoot></DIV></DIV>
<DIV id=3DrightColContainer>
<DIV id=3DrightColBody>
<DIV id=3DrightColBodyContent>
<H2>Related Content<BR><SPAN>from around the Web</SPAN></H2>
<H2>Other Articles</H2>
<UL>
  <LI><A href=3D"http://www.martinfowler.com/articles/rake.html">Using =
the Rake=20
  Build Language</A>=20
  <LI><A =
href=3D"http://railsforum.com/viewtopic.php?id=3D14216&amp;p=3D1">Restful=
=20
  Authentication with all the bells and whistles</A>=20
  <LI><A=20
  =
href=3D"http://www.rubyinside.com/19-rails-tricks-most-rails-coders-dont-=
know-131.html">19=20
  Tricks Most Rails Coders Don't Know</A>=20
  <LI><A=20
  =
href=3D"http://www.slashdotdash.net/articles/2007/12/04/iphone-on-rails-c=
reating-an-iphone-optimised-version-of-your-rails-site-using-iui-and-rail=
s-2">iPhone=20
  on Rails - Creating an iPhone optimised version of your Rails site =
using iUI=20
  and Rails 2</A>=20
  <LI><A=20
  =
href=3D"http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done">Ridi=
ng=20
  Rails: Rails 2.0: It's done!</A>=20
  <LI><A =
href=3D"http://www.railsenvy.com/2007/2/28/rails-caching-tutorial">Ruby=20
  on Rails Caching Tutorial</A> </LI></UL>
<H2>Screencasts</H2>
<UL>
  <LI><A href=3D"http://www.railscasts.com/">Railscasts - Free Ruby on =
Rails=20
  Screencasts</A>=20
  <LI><A href=3D"http://peepcode.com/">PeepCode</A>=20
  <LI><A =
href=3D"http://peepcode.com/products/rails-from-scratch-part-ii">Rails=20
  from Scratch Part II</A>=20
  <LI><A =
href=3D"http://peepcode.com/products/textmate-basics-for-rails">TextMate =

  for Rails</A>=20
  <LI><A=20
  =
href=3D"http://peepcode.com/products/benchmarking-with-httperf">Benchmark=
ing=20
  with httperf</A>=20
  <LI><A href=3D"http://railscasts.com/episodes/78">Railscasts - =
Generating PDF=20
  Documents</A> </LI></UL>
<H2>Documentation</H2>
<UL>
  <LI><A href=3D"http://rubybrain.com/">RubyBrain.com: Javascript =
enhanced Ruby=20
  API docs</A>=20
  <LI><A href=3D"http://www.gotapi.com/">GotAPI</A>=20
  <LI><A href=3D"http://www.railsbrain.com/">RailsBrain: =
Javascript-Enhanced Rails=20
  API Documentation</A>=20
  <LI><A href=3D"http://api.rubyonrails.com/">Ruby on Rails API</A>=20
  <LI><A href=3D"http://www.ruby-doc.org/stdlib/">Ruby Standard Library=20
  Documentation</A>=20
  <LI><A href=3D"http://www.noobkit.com/">Noobkit Docs - Ruby On Rails =
API... on=20
  Rails.</A> </LI></UL>
<HR>

<DIV style=3D"MARGIN: 20px auto; WIDTH: 150px"><A=20
href=3D"http://creativecommons.org/licenses/by-nd/3.0/" =
rel=3Dlicense><IMG=20
style=3D"BORDER-TOP-WIDTH: 0px; DISPLAY: block; BORDER-LEFT-WIDTH: 0px; =
BORDER-BOTTOM-WIDTH: 0px; MARGIN: 0px auto; WIDTH: 88px; =
BORDER-RIGHT-WIDTH: 0px"=20
alt=3D"Creative Commons License"=20
src=3D"http://i.creativecommons.org/l/by-nd/3.0/88x31.png"> </A>
<P style=3D"FONT-SIZE: 10px; TEXT-ALIGN: center">This <SPAN=20
href=3D"http://purl.org/dc/dcmitype/" rel=3D"dc:type"=20
xmlns:dc=3D"http://purl.org/dc/elements/1.1/">article</SPAN> is licensed =
under a=20
<A href=3D"http://creativecommons.org/licenses/by-nd/3.0/" =
rel=3Dlicense>Creative=20
Commons Attribution-NoDerivs 3.0 License</A></P></DIV></DIV></DIV>
<DIV id=3DrightColFoot></DIV></DIV>
<DIV id=3DrightColContainer>
<DIV id=3DrightColBody>
<DIV id=3DrightColBodyContent><IMG style=3D"PADDING-RIGHT: 8px; FLOAT: =
left"=20
alt=3DFeed-icon-28x28=20
src=3D"http://www.buildingwebapps.com/images/feed-icon-28x28.png?12097681=
51">
<H1 class=3DsidebarHead style=3D"PADDING-LEFT: 36px">RSS Feeds</H1>
<UL>
  <LI><A =
onclick=3D"javascript:pageTracker._trackPageview('/feeds/articles');"=20
  =
href=3D"http://www.buildingwebapps.com/redirect/articles_subscribe">Artic=
le=20
  Feed</A>=20
  <LI><A =
onclick=3D"javascript:pageTracker._trackPageview('/feeds/podcast');"=20
  =
href=3D"http://www.buildingwebapps.com/redirect/itunes_subscribe">Learnin=
g Rails=20
  Podcast via iTunes</A>=20
  <LI><A =
onclick=3D"javascript:pageTracker._trackPageview('/feeds/podcast');"=20
  =
href=3D"http://www.buildingwebapps.com/redirect/rss_subscribe">Learning =
Rails=20
  Podcast (RSS)</A>=20
  <LI><A =
onclick=3D"javascript:pageTracker._trackPageview('/feeds/blog');"=20
  href=3D"http://www.buildingwebapps.com/redirect/blog_subscribe">Blog =
Feed</A>=20
  </LI></UL></DIV></DIV>
<DIV id=3DrightColFoot></DIV></DIV></DIV></DIV>
<DIV id=3Dfooter>
<DIV class=3DleftFoot><SPAN class=3DfontGray>=C2=A9 Copyright 2008 =
Collective Knowledge=20
Works, Inc.</SPAN>&nbsp;&nbsp; <SPAN class=3Dnoprint><A =
class=3DgreyLinkUnderline=20
href=3D"http://www.buildingwebapps.com/privacy">Privacy Policy</A> | <A=20
class=3DgreyLinkUnderline =
href=3D"http://www.buildingwebapps.com/contact">Contact=20
Us</A> | <A class=3DgreyLinkUnderline=20
href=3D"http://www.buildingwebapps.com/full_tree">Site Map</A> =
</SPAN></DIV>
<DIV class=3D"rightFoot noprint">
<DIV><SPAN class=3DfontGray>Site design by</SPAN> <A=20
href=3D"http://www.raspberrymedia.com/"><IMG class=3DimgVertAlign =
height=3D25=20
alt=3D"Raspberry Media"=20
src=3D"http://www.buildingwebapps.com/images/raspberry-media-logo.gif"=20
width=3D119></A> </DIV></DIV></DIV></DIV><!-- end of pagewrapper div =
--><!-- ClickTale Bottom part -->
<DIV id=3DClickTale style=3D"DISPLAY: none"></DIV>
<SCRIPT src=3D"http://s.clicktale.net/WRa.js" =
type=3Dtext/javascript></SCRIPT>

<SCRIPT type=3Dtext/javascript>=0A=
  if(typeof ClickTale=3D=3D'function') ClickTale(10530,0.1);=0A=
  </SCRIPT>
<!-- ClickTale end of Bottom part --></BODY></HTML>

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/images/bwa_beta_logo.gif

R0lGODlhAwFGANUAAP/+/P///7sNBEdGRszMzHV0dKOiosxKQ92GgTMzM9HR0ZmZmb8cFO7CwFNS
UrS0s+Tj4vvw79VoYsQrI8/PzpiXl8g7M+qzsNBZU9l3cvLR0OWkodzc3PPz8+GVkbq5uV5dXYyM
jOjo6Pbh4K2trWppacXFxaempvj39cLBwfHx74GAgK6uruvq6NbW1N3c28nIx6CgoLu7ugAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAADAUYAAAb/QIBw
SCwaj8ikcslsOp/QqHRKrVqv2Kx2y+16v+CweEwum8/otHrNbrvf8Lh8Tq/b7/i8fs/v+/+AgYKD
hIWGh4iJiouMjY6PkJGSk5SVlpd8ApqbnAJZnaCYomOgnZ+lm6OqX6ipWK2aq7JbsJ6vsLOFDwu8
CzIoQru9vBAUw70QQioLLlK1p625hA8pEBAvJA/B1dbWKCrWxt3AADAkJM64t9HSgg8UQxALwfBI
8kUoMSonyVDP66jauasHgAI6AO+S3CPiQhuFFFH+XZEo0M+DEw8ekFjQIhjGjA9gEFk4hESzZeSc
UKyysuKejBRiniABDGZMCs3izRvSYgGM/5gxCDZpOYWoSzwJhaA4AS/pEZIAUnzUeMKfuolXj74U
SqKp0CIkUXAkEuOFFgJo06Y9oratVkTUuhlTgZBbN7pCSFKoSiSFjLNt1xoJLPitrmEkzCI8toAg
SaZFeuK9Qhgt28pQAmjezLmz58+gQ4seTbq06dOoU6teDZpKZQKXCWdmLboDh80cCugeXUH3B9wd
aAsXvuHAgQzDkwt3jXlwcyeaew+YPr1ABRGqRTgYUEGzAuqjC0w3EH2AA+zKNyMwjpxzA+MHRnCO
AD8CaQSaDpy+AF9C+uHMyeacgNAFIB51CA7wG2oGgBfAd9OFN55m1JH3XwAeaMJAZxlssv8BZxdo
MkFp+Amgn2kYcCLfhasFGFhsLz6h2YEFGGBABSBQpwBq2nHnnYOhHWhhBeah958Gm2jAmQWbtKdZ
hwL4d19+pkWgoSYesNjiFK/B6JaMBk6oWQc5DhBCarZtBuEAEg5gYQAcBKclA5p8qJmVm5yo2QF1
kkhlaRtoAqUFWqrm4pdFdAmmkJw1OEABwq3Z5puFapaiAE6GaKImnG1i35QmoqjJCBOMWulpXSSg
6qoJZDGjmJqFMF13AXygG62a2WqdZrnt9iCQAXRgQJkhiMBoAL0VsGCyAYgQQo4FmOCZs9s5YEAH
zGL4ZwAlltiAZg1oQuhmHvApgAUIfMr/bX4RIFCqABgo2RmeI0qAZWfsBXDBpRbYqVlxB2gQQQal
MiDBips1gAGdE2BwQWepsqqqq2G6udkH052nmaOQbsbxjxH+GjKcZVLnQJkWHnsgxglSqsB2COoW
MpKc7mmiplmui+mdTHZiwaclWtAzJ/7+K6i+4naWX4mcSKnzBXRywoC8AUDJiZOaRSwxxQeCoFuZ
INy2cXWNki0ym2dvVkLGFRgga4WvWlzxdiFUAPMA6PU4AAg2lox2AFF/G4CgNGNgqSaCmytBAwpr
IiXT8CKQQdQMIByAvQI8PLipm0mdwXqbIKAZ5AdITrl9NDOwQQMbLA4xFxJPjEXcCbop/2cAH3ts
tqRp10qd2L6LqXLGYncAs4VvlyBnB2uPfGmW4Wa++YiA1xyoAKJv9q59TGcfgAZRe1/9hocLkLNm
mzCgLubkd78Z+Pd2K5rWrHI9ndcFlOyA2LmP/SjIaOPdCqZzJs6gLG4pmxVn3tYxmElrMyYAUoai
pDP7mCsCI/jTpSxXooeViHybgZKeNOW0640LfffaDJ4E8K0PcohKE2SA4D5Dv1XZT24Pah4I/Ncx
HgLwhwFwYGeGJ7dj+ZAD1Lld776XtBSNy1s400zUUCG6EulJM5oSwGYwNwH4DA1hm5ihZnpWxW1h
cRMBiMAUJ5Auz9RQdldAIGfWJK3+4f9udw7inY6GKLw+4vCO/+OdmoAVteq1R1MIKJG8alHGULkH
jVKExfnCiC9NNPKKAYieFr83NAFM7XVSUFSintMEOXIGbnbMHe/0OJ0HboaICfzjx5A4HSUKMgDm
0pTm8CQBPoEwjIwLJuPkY8XOaIp6mmIAfIzzLj1Rckl9KiaIRAQizAmAeps5lFq8tM1FwapZ1PmN
o3a4GSL9r3e8O1ABN3M8UxoRkA2czoJyBawSXUpdpToAnZxmLjF2pkTYfJImDHc5xxnTUygUQNEy
qAklAbQzmCMoZ0YQNaoFQJuFIYIoS1kxSr0Nb2fbEZxg1rFVOogFv9OdH2NJqdy9bX//vLrbIzdx
woJ6aDMmVNc/N3E++Ck0ktJTWp82d011XYp6TOvpTXUagJ6JEaOWGVCMCkQjG+GIOriCmQMqEIK7
lTSPDiITdUJggOat1JQ+bJZXDwQsou6MXCqCpiclkMj15AxydJ1c0pioCaYG4FIE5QQbQacJzeHV
dHv1gMESeVRQRmGjQ4DsEmhXO1wFD0ERPKdJR8aBu02nBCxjKVrhiRvPOgClI7NZYTlDs2t2RgOd
3MTjsDRFEckLShLlzPUEYB+agsJJAK3tNeV1qU5oLptcImVklTtZZJm2RkZS0woc4IAQ3OZWvNJN
x3rVw2BVYG0luFavluWb6JT3Ytjd/0wHWLCCFbCgAxByQGcAdgCmwud8KvTA0CzgugAATAMaOGob
NdPLAxRNhfD5Vhg38C4MiNGKI+DigDMpgXdN4GBuTC6BNMpcJZzqw6phWXdBfKFngkaay9HwVDm8
YSaQ+MWdUWKwysQCGLPIxJ9BMW2gChupIoqjNn5xCFbwAQUowATNc4CMgywcHHtGx6xJglEikhUA
MPnFnsXsldPj5J06MsVHmLJV2DGELX+4A11N0AqAZ+YmI040UN5SmKtMhZW0GcQiMDKb78zn1EiZ
zkWpcp8HTehC/5nMVrBzoRfNaCYfOiAAKYVhJj0EMT/B0pTOBaaHAuhMC2TTTAC1pypHIWollHrU
lzg1ElSN6la7+tWwjrWsZ03rWtv61rjOta53zete+1oIQQAAOw==

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://s9.addthis.com/button1-share.gif

R0lGODlhfQAQAIcAAAAAAA0NDRAQEBMTExwcHB8fHzIPRABrJx1nLzZ/RUJ8JAAAkwA5oAANywAA
/x0g/x8h/zI0/zlcmDVHrhxZzlJ8s2ZttCGZACyzL1e8AFO7PGCtMkaoR0qgcXHNSF2Vy1Sc2GSa
1W7DjELG/7prAIddTrV0RP8AAP8ABOkfIv4AJv8zINg/TO53EP9nAOR3N/dkJf9pOv5tTP9zR/91
SP91Sf97Uf98U/99VNcY/rybFKyPKKeDfZbeLZ3bR8aQJtKmANi8ANy4APaPAfCJMf+qAPq3CcWO
S9apU/+GY/WxTtTGGPbNBPrRAPvDL/b2B/r6J8XFfvzMTouLi5CQkJGRkZaWlpeXl5mZmZqampub
m5ycnJeiqKSZt760m6GhoaOjo6ampqenp6qqqq6urquiuLCwsLGxsbW1tba2tre3t7i4uL6+vru7
xru8yr+/yZ3W/6TY4bfr/O6WgNbNuNvsvMDAwMHBwcLCwsPDw8XFxcbGxsfHx8HBzMTEz8rKyszM
zM3Nzc7OzsXF0cbG0cjI08vL18nN28zM2c3N2M/P29DQ0NLS0tbT1tXV1dnZ2dra2tvb29zc3N3d
3d/f39TF5dXZ5NXf6eDN7P/e6Pzf8P/j1ePj4+Tk5Obm5ujo6Orq6uzs7O3t7e7u7u/v7+3z8+/2
9vzk5fDw8PHx8fHz8/Pz8/T09PX19vb29vf39/b3+ff0/Pf6+vj4+Pr6+vv7+/r6///7//z8/Pz/
//3//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAMAADkALAAAAAB9ABAA
AAj/AHPksEOwoMGDCBMqXMiwocOHECPaETgQ0q6LGDNq3Mixo8ePIEOKHDkS0kQ7FkmqXMmyZcZc
ulx6NGkHY5KbOG/K3NmylU+fD4IG9ehojNE/HE8pIZIi00iCF5PcmEp1ahKeWEf+BBrUwQONatas
2RUIY56NtuY4gYGihIhddTbA8gh1l9QbNS7WsAoSgF+MAAAD/nvRL+FdhgOz3NrqQQShGcNcrBXm
yy5UlLSk0ajJRZETKjpw8JFBQSW6Ne3ijXExxt6rHhUjLix4Nm3btmX33PoAAmSMWHbV4oRlUqQ9
eexYuZVxU4sjK1gc8NDjQhnmHetK3XgDdkfdt3PX/5atGPxKxg8cqP+KccouUJCuvNKzZ0+n4BkP
wRlBwUsCDBoggMlHBOGCy3YadWfgggwaaNiCiQHgYGIT+gWhhQ1mqCEuESaCiCKJEGLgLLXscgUV
YrCxCCqpiHIGGQ2GIAcIDZggRRRL/BDLhgYSRAstUuFAw0U04NDdj0gmqSQAPzLZ5JNQMukklEpW
aWWTAxhmyJaG+PHjLLTMMgsWYgIyCiqSkAEmkpd8EAcDE7xgBBRNICHLlT8S5IorUtkww0Uz2NDd
noQW6goAhCJ6aKJ7Krroo446auiklB5KQAF+FaJpIX0UysodYNzBiiChrDGJGawQakoFEnCxgAFD
ML7xBBBdVEooQauscldVVuXq66+5GuYrAMMGW+wqxBqLrLDANussAAEI4Ncg1A7yBrB87GLHKo90
gocnaPxaiq+q8ECCEEHoYIGzvxJEyrsyxCtvvO/Wa++9+Oar77786hthGwADbG8oVGxBRShVaJGF
FgfvS8cObjRiSb0AkFJxxe8SxEgoHHfs8ccghyzyyCSXbPLJKKccCiMnLfLJyzDHLPPMNNds8804
56zzzjsvMpFAEgUt9NBEF82QQAEBADs=

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/assets/installwinxp_1click.jpg

[encoded data, 33044 characters]

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/assets/installwinxp_svn.jpg

[encoded data, 34048 characters]

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/assets/installwinxp_mysql_1.jpg

[encoded data, 31008 characters]
1qzqtNpKytoVGPKrH//Z

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/assets/installwinxp_mysql_2.jpg

[encoded data, 32604 characters]
XNL0002LjFRVkf/Z

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/assets/installwinxp_mysql_3.jpg

[encoded data, 31312 characters]
zZWk0vxVqutaPPqVhZwQWNyJWaGbJxxngn2r0CiioqVHOyta3YajY//Z

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/assets/installwinxp_putty.jpg

[encoded data, 26368 characters]

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Location: http://i.creativecommons.org/l/by-nd/3.0/88x31.png

[encoded data, 6460 characters]
GYZh/v2Uin3YYBDC/HcArOiX8zGX6zMAAAAASUVORK5CYII=

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/images/feed-icon-28x28.png?1209768151

iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABGdBTUEAAK/INwWK6QAAABl0RVh0
U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAZbSURBVHjalFZZjBRFGP6qq7pnmNlZjoXd
lXuFIIcbZFmDJC7xgYBKYnggiD6oCEQRXrwSEoMafFVMfEBi8EAhMRjhgcASUBINIBoQFIUIC3LI
scsCe87szHR3+f/V3dMzS0h0Zv6p6u6q+ur7j69aaK3x24tjLABLqb+C2iYyaPry766+Djt8V/+n
9jo1X9HFtrlfd10VJ5ePZjDPFhKZcdOgpAUhBEB3hUUt9YVlGtNaVvjM3CdTFvgWJD+nvozG8wQN
TyTQ2T6Am2dPo3Dr2lxFQ5cz2PAJD8K78w88txBOEtARKG/JChbU4YLgjSlhxprxxggwHCfCcUoq
jK0bimR6Jtq+u7pakYtWZ8ZPg09g8AoEIuCG/pM0UdHOLSFKCwhmQgtLFWzKUhGYMOxFyRC4RfvQ
xT6kHMlebmSGs5Ul4ROYT8/znkZqzmKkJzXBvfk3vFsXyS4AvVehaAOSWahyVhGzECjyAEQYBzLf
RSolOf6zGNAMZlcxsTxFesS0FgxrXoToo8nNhfY25M8fgdt2EKLzTAwky1hxXwwCQ3iNoK9M1oWx
4q4WPgZ/hHKQGDPdGFpWIH/hEAqHP4LquRQyKnPjYDAdgzJWMCScQPGFY3OrcM8PLZSY1IKqZV9A
PLwKvkyE7kQMNBhMC0TVpALAIBlsGlhF8ezb9wH6j2yFVT0Sdu0kJCfORqqhGZadjHGdNJJzVsGd
8Aj8H96Blb0Rs4Mo1S2nuo5A6WtcarItTH+bTGevQ+RvQNymwVd+RO+xz9Bdcz/STUuRaVwEmawu
Aav6RngLNsLd/zrkQEcIJoLC99mKlP0+fCtrNhG4VAbGdedSCHX9VFgNc2DVjIPt2EgNUUjnrqB4
6H10bH0WPX/srfCyHD4R6vEP4afuAwq08EAXdN9Nsnbo3g74ZCjmzSYU/wWqYcEltlmy2paVqG5c
CO0V4XVdRf7MHuhz++AQA9fvRPbgu3BvX8CIeWtj0KHjKaHWw/tmCe2a6jmMm6ZaYxNammuL/4ya
hGnO3vD9IABC2lA1E5F+dA1Sz2yHnLMGTjKJjOiD+/NGtH+71pRMCZTci+ZXwLloAA0YrxcYzBNm
yGpCxSwpQxVpo0pl7kpOi+KWaHoO9lNbIDN1SEsPOLcbHXveqhhnN62AP3QyeQfG/PI2YmgZ0SUg
Ak0NkRg404rekzsxcO0UDXYr41UzGc7iz6GGj0fasVA4tQM9f8YxFYkqqHnrSqwYiITGgN7FUDkK
qYQF5+xOuK2vovfThejYPB/dx7ZXsh1GSfLkJkgnYUDvtG6Al+uOWU5+DBjVWMGOwWOGrPwM6vVD
5TvgeF1I2S4ypH+p3Hnk9q9D5971RohLTOsaoea+aWpXUg12n9hVrg6wpiwssYvamCHFTeQ6IQq3
4dOiRQp4ngLOraJkyiQteL9/ifZdrxGmWxavFyBHPQCHkq776Db4xYG4PkmNeKgXWhxD3k+hh/ZE
qUw0GagvPQHJ5w8g88YlJF86AXv0Q8Z17pldxGRHGREJOWMJnSICfmcb+tqOxoC1U4DqcTHLEkNW
Gi9LMaQjiibm6HjKLNgAp26acY1I1cBevBUOMU1SFncf/oSY5OKFG+bRMJsPfPSd/6VC8EEJFoHp
0DGh0ljBaUHxcMmNifrplXqdHGYOF5tF985F5C6fKFOZBsiqMRDkmYHr5yqTi+TQuJTVzQvehyyj
pTJ4JZBkNln++qmKiTp3xxQy6zIzybf/VVYnJFbVY8Gnmtdzs2KeGtkAltIocSpPCxEkSJoOhP4D
bxO4gjN6ptFD9+B6s6BFoOxa78pxZM9OIoQ8JL9C9HfTQnS/p5Ni3GrocPrn234NYkigInSp+GnZ
MN38xCyg64I5WljVXC8QceJNjIR5K9NhERcpxlHmGVlkLQwTo+hq4z4dXvMzHcZQ1U1G29nvTQyP
5wZopkoG9YPArUOoVDjdI7DIJJcKj2GPUN9iV4VmURz5ObdWCGY2Rq+K+UBzj3MMt3ScPg2RrqMZ
ifiwDJVBl0vUvSyqtWJcAqbPbJEgORyHrosmL/YKTpojTw/dVFufXF07dQaSKbsEhhAscif8Mpny
gswzBe3G4JGUGWY+u7mA25dPIovejwnrPRG9uh9eWv0yDVlJl7P/x2t8+Ppf3tdxdgf942Rb5u92
N/PFvwIMALhpLlqah3+YAAAAAElFTkSuQmCC

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/images/raspberry-media-logo.gif

R0lGODlhdwAZAPcAAOTl6enq7fHT1bzAyIVNL8DDy+fpy8NCTbwxPKisucvDaq2DS9d5hPz29cI+
SpKKR7GzWdze48taY9qLkdN0fPns7frv7/T19uOlq+3t8LNGRbhjZtRXaME0Rd6Vm5BXVbwsO93i
s9iEiqGnrq+zv/rx8qSpttRMXcRGUPz8/cZJVfTd3rK1v/LY2vb2+PXh4p6jstBqc8dSXKOntcIn
O410duvAxOm7vs1CUvL03r40QfHy9N+aoPX265grKJaIN2xaLrO3wuCeo5yhr5qersilouzFyNrb
39/g5c1KXOq9wMo5Tbm8xss+Ud6Ynvjq6/n68uautMY1SeGhprW6xJacq+Hi5u/MzsE5Rv78/M3Q
185lbadMS9Rlc+rx88gyRpZlZZqdo8bJ0M9ncO/N0Js9M/bl5qcqLPv09LtHUM1ha8o2Svbz4bol
NNDS2fj4+q2Nkry/yce+xPr6+/z4+NeCiOa2udHU2snL0/77+tyDkJeWnMzO1b1ATPXe4MrM1Kk3
NYgeGOi3u9RueO3IythufPfn6NFSYtuQlqywu/77+8XJz/Pa28dOWfP09W4bFMUuP5GWpvv7/Pr5
+vf4+e/v8fTb3eLg464yONfZ36g7POSqr/7+/evr7uLk5/LW2O/O0NPW3P////39/v7+/v7+////
/v3496ert/7//v7///f3+P3+/v/+/+jp7Pv8/P/+/s1daObn69XX3f36+vPh3ufj5rU8QNBEVquh
pq+sstfO093aj4l9Rezt0499gLgfLsqQlpc2MfTz88K5ePPc3MPGz7wrOOLb3L5UW8O2vPTi4fLl
5ujgmcKsra2DgKiXnLOFjXo8Orq3j+3r7ueyt9qHjv78+9zfuLYmMN+Mm83NoNPVoNHIVLkwP8ZM
Vtq9u4wvLYwzM9/iwpmUOrqOl8O2RMjM0o+EiJOKj5KMkf79//3+/Nd/h+Tbq/n6+vv7+L22bVEc
HkwoEIqSKuXBxuTl5u7KzaWqcK0sMb+2cs7BhaxocbC1vM5jbaQ3NiH5BAAAAAAALAAAAAB3ABkA
AAj/AEUJHEiwoEEoOQwqXMiwocOHECNKVAilx0ADISZq3Mixo0dRbHhBEdUDQkZTbCx+XMmyJcQQ
3Zr5wkcPGxt3BuC53MnTZSoF5hRA6PWA2L6EPZMqlciOk6hx5H48+PGj14IFNrIs3cqVIBRuEOLp
6wWEQBkNGm59k/KFR9e3Sk0Z2DYNyLxH4WS0oaCNxpJCgyRUcKnoiSK4Dt+s+mhKoBx54jQg0AGC
gp4luDgcamLH5QsVjBA3/ENCVBwmpDoOkxbo34Y0tzp88csjyhoaMhq0fIKFjGiGxkyIIkEiNUdn
j3z4wOTNm2xIa/RgwJHkQC2CWQaLqqBdoIUWukVd/xOV5ZTAJwdapAo/0AL71GjQDKwAa9TCNwJH
TSI4ZzFBSaL8gYooraQw0CrvTPRMIJpocgYNDiCSxBdfNLHGF2s4sIIopwzCQyOIGLHFNwdYQ4so
m6DwzTdXGKIGIhKg4AEsFaBgjQQHiJAHh3WsKIQoAozBwwGE1OGEBCJQIIhALYzBDBV8kEDEHRGg
MsQdAmlhwgxxzCFKCgXMQAULiYgiBh+iZELCDDBoIVERPmyQTB9jYFFIEhzoIUUXh9CABSiiNHCA
DlM8wYMTfhgBwj1mYHGDBUaY8UIbEthgxzFRNIBFLDYooYMTorQjAyNG6GDECm3IIAgdsYDAgyGD
xP8gkAjfTALDDBHcEUkiSOBBxCiZEAFAADMUYBoMnniCSpkkxCGKMW5kkEkVlUQEjg+aYILAAVIs
sQYHXUhhDQOQqHDdKSggQlAFnxxgQwvH2DDQCjoAKooIalhwgAACeYCCBTrcIFAMDLyARQsCqTGB
QIJgUYIoB/w4AxKirDKELKJ0MsQqCTAhEB4zrEJEBB8nIEoQAwzkAgDCGlTKKClIopgjjiDDhQ8a
OIBAEoVI0e0XS2DWjkDoYsBkDDFsAYINo4iAgAoUWPCCDr6JIoQKy6BgLwZ/IuAPBRQ0MgEjB7yQ
sFuilICCEQaHNoMVouwAQyeiyDKEI6jMwAQTCVD/kUEVOwgkhskoiwIACUEkUkUABJGinyMZuOLJ
EXeIUQAYgWzgDwpJnABJFxickEQTNAzNIQpTpH3ABLSggYISAlmyiQMx+PGnQEI0YgYK/IoyBRbF
6GDDE4ZYQMsnDviRMKgCUdAOBjKIwsrEccPAuN0XmFCAC464MMrf1YqCB+EFrFKFFqNUMgTdAq2T
wiqVyHKEG2IM0M8Ie9QgDCD59KHGMU3AAQeacIgTSKEeqjhd6gTQBrOZQXiwGEgU0tMBeYliDAxo
gAMEJootjEEUKliYKEZxvOQtbyBKkMAWPDBC6sntekOYAxMGJJA5zIEIbhAI305WAFlE4gKiCAAR
/zIwkMd1AgluWMQAgoCKMKjjF2AQxhnS0IdsHAIXmMEFDoLhBQOdwgE/akAjYrGJMQCDEKCQwBQw
gDpD6EBGFMCCJSrwtDrEQAf8UgICKHAkUNBLeaKQAAvP4wAQmG0UMCDZDojgCsNVgRI7GEIiovQH
UbihCnGgQhVM1ixKEIEJoUhEJBiXnzk44oh3OEcBqJAI/KGjBh/4wD/O0AZI4AASNJDCBgrgCgBl
wQaANIQTJkAIIxgCDdWwRjuWZDsMeGACyiuBEhgxzNAI5BOImIASFCFN+YiCEJYYiCli0YjDlAIJ
QJxDBChRsQi8QhSO4IMxZuECgXgCD7MIANwA0KrIDCzCGABAZxFfsYodyCICoeCDEu8XhnT8ApZl
wAQIOpAGfsBBGUe4ACs2Qq/euSQLEviRaEiRgjc4ohIBCOj86scCXeQiF9CAQzTK4Qw57MIWF7DP
RiyhgyvwRARjMM9vSvEySUxiEqu4wA4q0QlXAMAKl4iqPVxBjUpcYA7G2UgDQMGelgigq78RSCsE
UopUkMJxo0hrWllBClW0Naxwjatc50rXurYkIAA7

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/images/search.gif?1209768151

R0lGODlhRAAWAOZ/AK0BAeekpOWGhs01Nd07O+U8PLwxMddCQrUBAeo8PKFYWMtFRfYaGrEBAeJB
QeOVlZcnJ/EkJMMBAfHKyt0zM9p4eLQvL/YfH9MBAeJtba0tLcsBAfU1Ne28vNpubvEpKdU0NMY0
NPQlJeYxMehqatU4OLkBAfIfH/zy8uyTk9oBAb4BAeE0NPXX1+UrK+koKNFQUO0oKO4kJO0tLfYv
L6GRkeksLNVnZ/Y5Od2Hh6cBAepDQ4okJPYqKt3d3cY4OONcXNheXso6OrsSEvE8PLOzs/ru7ugy
MvRra/rk5O0yMuJ3d+AwMNNdXeKZmfXd3fIuLu9AQOpkZO43N+k2NpmZmf///6IBAZwBAf1kZP1p
afxdXfxYWPxgYKcsLPxVVaAqKv1sbPpubvZvb/FwcKSkpOzs7MLCwpqamvCOjt8BAb4jI/Q9PfE4
OJ5CQpqQkMEjI89WVu/KytIjI/fk5Ks4OKYREfJjY/thYdhQUJmMjOFoaO2hoddra9pnZ////yH5
BAEAAH8ALAAAAABEABYAAAf/gH8+RVWFhoeIiYqLjI2KRT5/ZjUEDJaXmJmam5ydmV+goaKgezVm
ZzAXqqonra6tq7Gys7OvsLRcubq7uh5nZUoiwiIRETLHyMXDy8zNw8XGyRHOW9XW19Z3ZWg93T0f
HzEv4+Qx4Ofo6ernMeLl597dXfP09fR4aFU0+1BQMzYuXEiRssOFDRszEipcyLDhQYBp0hhE2G/f
viwYM2rUWIiDRw5KjoxIYaWklSRMRqhcOUIky5ZHYspcyYRJyZotlXz0qKVnTys+g2ophKNomylU
BFhpsWQPHxQUojogQYICi6tUgUS9ypUr1QMgSoIAAoQFlSltiuIIw5ZtSSRt/9sWYsOGCJEEBUh2
CDJgQB4QIJSWbAHW5Mm/JVOgyCAAhckgJSeU5FMgQQIidMVo1mwSyWbNhaKIxksgg0kUHZoMgDxh
wAMrAQbkWDCgg5UHA0oGeAAZhQAPHfqUzPHaCoHKoqOMWb7cMBLmYwrtmO7AAYESwB1bQbHgNZ0J
LaxM+JFDjvYHP0oKEfI6gJAf8EvGN17dwXQy+PEbtkIifyE1AKqgAgZzSLDCCiE8YcUCFVjRQQUQ
3nCDeDc4YUUFK5QkgQQNCnDggSWBaMUGGAgIYAEoomiYBgMcV0AhAmIg4wZLPLhAHEYYMUQIVjwB
BwIhQGhFDghYWIEJIa6Qm/8RNzDIoxUmZDgiiTKqQMCVV5rEAwQWlHBlITNusIEEfhhh0hNxmIDA
DWbqtoaZRkh2ZElRmsCmSU+agKQVG4opYwmAAloSDzyAYUCghYi54YYrmLDAAiEgIOmkj64h6RAL
DDEpAnp2quejmkra6YGLSrBBX6haAcGWFoSAaiEfHqjnprRO2sCtuN5Kq5q17hplrCEEG6wFEECg
gbDBFjLrprk26+yzuiIAbbS+GmCttRqA4cW111aBBq4AhCvuuOSWa+656IZ7qwXstqtBu/CiUYYd
OtRr77345qvvvvzmq8G/AAcMcB1lnOHGFQgnrPDCDDfs8MMMeyHxxBRPrMAoGWboAQEWHHfs8ccg
hyzyyB+DYfLJKJvsxhtmCEKIIzDHLLMjkPwRCAA7

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Location: http://www.buildingwebapps.com/images/submit.gif?1209768151

R0lGODlhSQAWAOZ/AOyUlOOGhtI2NuU8PNNERM02NtU5OfEkJLwxMbUBAfUaGrkBAcMBAdh3d7EB
Ad47O59AQNZdXew8PN4zM/XJyeVCQvUfH9EBAZgoKPEpKe27u7QvL8U0NK0tLeUxMfY1NfIfH60B
Ad5qasoBAZuVlektLdkBAb4BAewoKOkoKOJsbOwtLeUsLMbGxu4kJPQlJco5OaampukyMvYqKvYv
L8tFRetDQ8Y4OIokJNoyMuRcXPvy8t6Hh+E0NPZqauJ3d8QSEssjI/c5Ofru7vbW1uAwMNZnZ/E8
POU1NfAuLtFUVPGPj6cBAfBAQPbd3fI4OO43N+k2Nu8zM9g2NupkZLsSEv///5mZma2traIBAZsf
H/1kZP1pafxdXfxYWPxgYKcsLPxVVf1sbPpubvZvb/FwcKgBAZqamvQ9Pd8BAff39+/v77m5uePj
483NzfHx8eqgoO/Kyu2urqBjY9IjI6YWFvBkZJ1cXPthYfvj4+JhYao8PJ1OTu5tbdlvb////yH5
BAEAAH8ALAAAAABJABYAAAf/gH9tbFeFhoeIiYqLjI2OV2xtf2skBAqXmJmam5ydnp9hoaKjoSIk
ay1KFqurIK6vrqyyFrAgs7eytbG4Xr2+v74NLTEyL8YvBwcuy8zJx8bJysvOz9XQ0cwu1NVd3d7f
3nYxZzPlMxkZKCnr6ygo6PDo7u3u8fb27vn16OblX/8AAwLEc+YKjYM0kqwowYIFFSo2WJRYQTGJ
whIMlyxpiJGix4UTQWLU2JDjCosIaWxZybJly0IfYn6QIsPDEis4reTx4EGGz5o8i+AsQrQnUJ5I
k3oYWoQChZ5SpMj8wKVqVStWs3IpJKTrEyhRAlgh8kMEnB0TeqhFgqTHhAk5/3DmUKEjrdq3OupO
yJsWbo6/OHsgiQLlSVchYhInxulDseJCaNAckSBhAAArGiIUKKBEwBScUz5bESAAJxGccELjpIBT
DmsrqUuPfm2FwgAJRyKjGcObd04fvXkXakK88gMVOXdkLiCbNM7NOHk0wElAdgAeOAOIHV3geQSc
KvQ8GECcOJnz53Na6YOeTCEb8CtUeGDAj4YdOHfUgIETBn8rN9yAU4BxWOHHfzAIaIV//f0XIE4G
GPCAfPDZUMaFF6q3HoaFpOGhCSZcQAcDJ5zAgRNWEHACTiWyuKIVJWqQ4ostwvgiAwy4iNMII1wA
oodpDCCkkOp1UMB4AxQCYv+IF4zwgwYN1KDEEEMAsQBODRiB0wJXWrEAB1YMscCLXG7ZZY1j4gRE
ED36COIDcMKZEw4YbCAAnIVcoCePDBgxRE5OKMEldpjhlEACOP1phRFletllo5AuQKgGDPCo5wUR
ZooTDnQiIECEhfA4Ao4kLlBDDRwcqioHqaqqahU1VJEAl7TWaqutHNQQBKmibuarFRjQuYGvBRRS
4rFcuqrsssw266yqtB5bIqvUboABBh1Qy2ohybrqwLfghivuuOIe+q25DqAb7rJcIuCuux1gAMa7
715xhrgh5Kvvvvz26++/AOcr7gYEF9xBwQifEUMdZjTMxMMQRyzxxBRXbHFYxA033MHGHHfM8R4x
uMFHFiSXbPLJKKes8sosZwHGyzDHDPMcbqhBAgRa5Kzzzjz37PPPQAcNwdBEFz30HSSo8ccbLWDh
9NNQRy311FRXbfXVWLTwxh+BAAA7

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/stylesheets/main.css?1209768151

HTML {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 12px; BACKGROUND: =
url(/images/bg.gif) #fff repeat-x 50% top; PADDING-BOTTOM: 0px; MARGIN: =
0px; COLOR: #333; PADDING-TOP: 0px; FONT-FAMILY: Arial, Helvetica, =
sans-serif; TEXT-ALIGN: center
}
BODY {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 12px; BACKGROUND: =
url(/images/bg.gif) #fff repeat-x 50% top; PADDING-BOTTOM: 0px; MARGIN: =
0px; COLOR: #333; PADDING-TOP: 0px; FONT-FAMILY: Arial, Helvetica, =
sans-serif; TEXT-ALIGN: center
}
#pageWrapper {
	MARGIN-LEFT: auto; WIDTH: 960px; MARGIN-RIGHT: auto; TEXT-ALIGN: left
}
A:link {
	COLOR: #bb0d04; TEXT-DECORATION: underline
}
A:visited {
	COLOR: #bb0d04; TEXT-DECORATION: underline
}
A:active {
	COLOR: #bb0d04; TEXT-DECORATION: underline
}
A:hover {
	COLOR: #ff0000; TEXT-DECORATION: underline
}
A.smallLink:link {
	FONT-SIZE: 11px; TEXT-DECORATION: none
}
A.smallLink:visited {
	FONT-SIZE: 11px; TEXT-DECORATION: none
}
A.smallLink:active {
	FONT-SIZE: 11px; TEXT-DECORATION: none
}
A.smallLink:hover {
	FONT-SIZE: 11px; TEXT-DECORATION: none
}
A.smallLinkUnderline:link {
	FONT-SIZE: 11px; TEXT-DECORATION: underline
}
A.smallLinkUnderline:visited {
	FONT-SIZE: 11px; TEXT-DECORATION: underline
}
A.smallLinkUnderline:active {
	FONT-SIZE: 11px; TEXT-DECORATION: underline
}
A.smallLinkUnderline:hover {
	FONT-SIZE: 11px; TEXT-DECORATION: underline
}
A.greyLink:link {
	COLOR: #666; TEXT-DECORATION: none
}
A.greyLink:visited {
	COLOR: #666; TEXT-DECORATION: none
}
A.greyLink:active {
	COLOR: #666; TEXT-DECORATION: none
}
A.greyLink:hover {
	COLOR: #999; TEXT-DECORATION: none
}
A.greyLinkUnderline:link {
	FONT-SIZE: 11px; COLOR: #666; TEXT-DECORATION: underline
}
A.greyLinkUnderline:visited {
	FONT-SIZE: 11px; COLOR: #666; TEXT-DECORATION: underline
}
A.greyLinkUnderline:active {
	FONT-SIZE: 11px; COLOR: #666; TEXT-DECORATION: underline
}
A.greyLinkUnderline:hover {
	COLOR: #999; TEXT-DECORATION: underline
}
A.blackLinkUnderline:link {
	COLOR: #333; TEXT-DECORATION: underline
}
A.blackLinkUnderline:visited {
	COLOR: #333; TEXT-DECORATION: underline
}
A.blackLinkUnderline:active {
	COLOR: #333; TEXT-DECORATION: underline
}
A.blackLinkUnderline:hover {
	COLOR: #666; TEXT-DECORATION: underline
}
A.whiteLink:link {
	COLOR: #fff; TEXT-DECORATION: underline
}
A.whiteLink:visited {
	COLOR: #fff; TEXT-DECORATION: underline
}
A.whiteLink:active {
	COLOR: #fff; TEXT-DECORATION: underline
}
A.whiteLink:hover {
	COLOR: #f1f1f1; TEXT-DECORATION: underline
}
P {
	MARGIN-TOP: 2px; MARGIN-BOTTOM: 13px; COLOR: #333; LINE-HEIGHT: 1.3em; =
TEXT-ALIGN: left
}
P.paraMarginTight {
	MARGIN-TOP: 4px; MARGIN-BOTTOM: 4px; LINE-HEIGHT: 1.2em; TEXT-ALIGN: =
left
}
P.paraMarginSuperTight {
	MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; TEXT-ALIGN: left
}
P.paraLast {
	MARGIN-BOTTOM: 0px; LINE-HEIGHT: 1.3em; TEXT-ALIGN: left
}
H1 {
	FONT-WEIGHT: bold; FONT-SIZE: 150%; MARGIN: -3px 0px 0.7em; COLOR: =
#333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
H1.h1TightMargin {
	FONT-WEIGHT: normal; FONT-SIZE: 140%; MARGIN: -3px 0px 7px; COLOR: =
#333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
H2 {
	FONT-WEIGHT: normal; FONT-SIZE: 130%; MARGIN: 0px 0px 0.6em; COLOR: =
#333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
H2.h2TightMargin {
	DISPLAY: inline; FONT-WEIGHT: normal; FONT-SIZE: 130%; MARGIN: 0px =
0.2em 0.4em 0px; COLOR: #333; FONT-FAMILY: Verdana, Arial, Helvetica, =
sans-serif
}
H3 {
	FONT-WEIGHT: normal; FONT-SIZE: 120%; MARGIN: 0px 0.2em 0.4em 0px; =
COLOR: #333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
H4 {
	DISPLAY: inline; FONT-SIZE: 100%; MARGIN: 0px 0.2em 0.4em 0px; COLOR: =
#333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
HR {
	MARGIN-BOTTOM: 18px; COLOR: #ccc; HEIGHT: 1px; TEXT-DECORATION: none
}
.fontBreakoutTitle {
	MARGIN-TOP: 0px; FONT-WEIGHT: normal; FONT-SIZE: 16px; MARGIN-BOTTOM: =
8px; COLOR: #fff; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
.fontWhite {
	COLOR: #fff
}
.fontWhiteBold {
	FONT-WEIGHT: bold; COLOR: #fff
}
.fontGray {
	FONT-SIZE: 11px; COLOR: #666
}
#header {
	MARGIN-BOTTOM: 16px; WIDTH: 100%; POSITION: relative; HEIGHT: 128px
}
#topHead {
	HEIGHT: 70px
}
#botHead {
	HEIGHT: 29px
}
#subNavContainer {
	MARGIN-RIGHT: 0px; HEIGHT: 33px
}
.leftHead {
	FLOAT: left; POSITION: relative
}
.rightHead {
	DISPLAY: inline; FLOAT: right; POSITION: relative; TEXT-ALIGN: right
}
.rightHeadSpacer {
	PADDING-RIGHT: 3px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 21px
}
.rightHeadFormWrapper {
	DISPLAY: inline; MARGIN-LEFT: 10px
}
.subNavAlignSeminars {
	FLOAT: right; MARGIN: 5px 100px 0px 0px; POSITION: relative; =
TEXT-ALIGN: right
}
#leftCol {
	FLOAT: left; WIDTH: 740px; POSITION: relative
}
#rightCol {
	DISPLAY: inline; FLOAT: right; WIDTH: 220px; POSITION: relative
}
#subCol {
	MARGIN-TOP: 14px; FLOAT: left; WIDTH: 731px; POSITION: relative; =
TEXT-ALIGN: left
}
.leftSubCol {
	FLOAT: left; WIDTH: 225px; POSITION: relative
}
.rightSubCol {
	DISPLAY: inline; FLOAT: right; WIDTH: 506px; POSITION: relative
}
.leftSubColEven {
	FLOAT: left; WIDTH: 356px; POSITION: relative
}
#leftSubColEvenContainer {
	FLOAT: left; MARGIN: 0px; WIDTH: 356px
}
#leftSubColEvenBody {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/editorial-bg.jpg); WIDTH: =
356px; BACKGROUND-REPEAT: no-repeat
}
#leftSubColEvenFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/editorial-foot.jpg); MARGIN: =
0px; WIDTH: 356px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 15px
}
#editorial H2 {
	FONT-WEIGHT: bold; FONT-SIZE: 16px; MARGIN: -3px 0px 0.7em; COLOR: =
#bb0d04; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
#editorial H3 {
	FONT-WEIGHT: normal; FONT-SIZE: 13px; MARGIN: 0px 0px 0.6em; COLOR: =
#bb0d04; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
#editorial A:link {
	FONT-SIZE: 11px; COLOR: #333; TEXT-DECORATION: underline
}
#editorial A:visited {
	FONT-SIZE: 11px; COLOR: #333; TEXT-DECORATION: underline
}
#editorial A:active {
	FONT-SIZE: 11px; COLOR: #333; TEXT-DECORATION: underline
}
#editorial A:hover {
	FONT-SIZE: 11px; COLOR: #666; TEXT-DECORATION: underline
}
.rightSubColEven {
	DISPLAY: inline; FLOAT: right; WIDTH: 357px; POSITION: relative
}
#rightSubColEvenContainer {
	FLOAT: right; MARGIN: 0px; WIDTH: 357px
}
#rightSubColEvenBodyGeneric {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/on-the-web-bg.jpg); WIDTH: =
357px; BACKGROUND-REPEAT: no-repeat
}
#rightSubColEvenFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/on-the-web-foot.jpg); =
MARGIN: 0px; WIDTH: 357px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 17px
}
#ontheweb H2 {
	FONT-WEIGHT: bold; FONT-SIZE: 16px; MARGIN: -3px 0px 0.7em; COLOR: =
#333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
#ontheweb UL {
	PADDING-RIGHT: 0px; PADDING-LEFT: 20px; LIST-STYLE-IMAGE: =
url(/images/bullit-square.gif); PADDING-BOTTOM: 0px; LINE-HEIGHT: 19px; =
PADDING-TOP: 0px
}
#ontheweb A:link {
	FONT-WEIGHT: bold; FONT-SIZE: 13px; COLOR: #333; TEXT-DECORATION: =
underline
}
#ontheweb A:visited {
	FONT-WEIGHT: bold; FONT-SIZE: 13px; COLOR: #333; TEXT-DECORATION: =
underline
}
#ontheweb A:active {
	FONT-WEIGHT: bold; FONT-SIZE: 13px; COLOR: #333; TEXT-DECORATION: =
underline
}
#ontheweb A:hover {
	FONT-WEIGHT: bold; FONT-SIZE: 13px; COLOR: #666; TEXT-DECORATION: =
underline
}
#ruby {
	FLOAT: left
}
#rubyBody {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/ruby-bg.jpg); WIDTH: 356px; =
BACKGROUND-REPEAT: no-repeat
}
.landingBody {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/topics-blank.jpg); WIDTH: =
356px; BACKGROUND-REPEAT: no-repeat
}
#rubyBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
#rubyFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/ruby-foot.jpg); MARGIN: 0px; =
WIDTH: 356px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 82px
}
.summary {
	FLOAT: right; MARGIN: 0px; WIDTH: 357px
}
#summaryBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
.topicsFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/topics-foot.jpg); MARGIN: =
0px; WIDTH: 357px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 13px
}
#topicsBodyUi {
	MARGIN-TOP: 14px; FLOAT: left; BACKGROUND-IMAGE: =
url(/images/topics-ui.jpg); WIDTH: 357px; BACKGROUND-REPEAT: no-repeat; =
POSITION: relative
}
#topicsBodyServers {
	MARGIN-TOP: 14px; FLOAT: left; BACKGROUND-IMAGE: =
url(/images/topics-servers.jpg); WIDTH: 357px; BACKGROUND-REPEAT: =
no-repeat; POSITION: relative
}
#topicsBodyDev {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/topics-dev.jpg); WIDTH: =
357px; BACKGROUND-REPEAT: no-repeat; POSITION: relative
}
#topicsBodyBusiness {
	MARGIN-TOP: 14px; FLOAT: left; BACKGROUND-IMAGE: =
url(/images/topics-business.jpg); WIDTH: 357px; BACKGROUND-REPEAT: =
no-repeat; POSITION: relative
}
.summary H3 {
	FONT-WEIGHT: normal; FONT-SIZE: 16px; MARGIN: 18px 0px -3px; COLOR: =
#333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
.summary A:link {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.summary A:visited {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.summary A:active {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.summary A:hover {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666; TEXT-DECORATION: none
}
.learnmore {
	RIGHT: 0px; WIDTH: 150px; POSITION: absolute; TOP: 0px; HEIGHT: 35px
}
.bucket {
	FLOAT: left; MARGIN: 0px 0px 15px; WIDTH: 357px; POSITION: relative
}
.summary {
	MARGIN: 0px
}
.bucketBody {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/buckets-bg.jpg); WIDTH: =
357px; BACKGROUND-REPEAT: no-repeat; POSITION: relative
}
.bucketBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
.bucketFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/buckets-foot.jpg); MARGIN: =
0px; WIDTH: 357px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 16px
}
#bucketLabelBanner {
	PADDING-RIGHT: 0px; PADDING-LEFT: 10px; FONT-WEIGHT: bold; FONT-SIZE: =
14px; RIGHT: 0px; PADDING-BOTTOM: 0px; WIDTH: 110px; COLOR: #fff; =
PADDING-TOP: 10px; POSITION: absolute; TOP: 0px; HEIGHT: 35px
}
.bucketLabel {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; FONT-SIZE: =
14px; RIGHT: 6px; PADDING-BOTTOM: 0px; WIDTH: 150px; COLOR: #fff; =
PADDING-TOP: 1px; POSITION: absolute; TOP: 2px; HEIGHT: 35px; =
TEXT-ALIGN: right
}
.bucket TABLE {
	MARGIN-TOP: 10px
}
.bucket H2 {
	FONT-WEIGHT: bold; FONT-SIZE: 18px; MARGIN: -6px 150px 0.7em 0px; =
COLOR: #333; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
.bucket H3 {
	FONT-WEIGHT: bold; FONT-SIZE: 14px; MARGIN: 18px 0px 8px; COLOR: #333; =
FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
.bucket UL {
=09
}
#banner_more UL {
=09
}
#content UL LI {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; LIST-STYLE-IMAGE: =
url(/images/bullit-square.gif); PADDING-BOTTOM: 6px; PADDING-TOP: 0px
}
#content UL {
	PADDING-LEFT: 20px; MARGIN-LEFT: 0px; PADDING-TOP: 6px
}
.bucket UL A:link {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
#banner_more UL A:link {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.bucket H4 A:link {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.bucket UL A:visited {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
#banner_more UL A:visited {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.bucket H4 A:visited {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.bucket UL A:active {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
#banner_more UL A:active {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.bucket H4 A:active {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #333; TEXT-DECORATION: none
}
.bucket UL A:hover {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666; TEXT-DECORATION: =
underline
}
#banner_more UL A:hover {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666; TEXT-DECORATION: =
underline
}
.bucket H4 A:hover {
	FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666; TEXT-DECORATION: =
underline
}
.bucket HR {
	MARGIN-TOP: 15px
}
.moreArrow A:link {
	FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #bb0d04; TEXT-DECORATION: =
none
}
.moreArrow A:visited {
	FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #bb0d04; TEXT-DECORATION: =
none
}
.moreArrow A:active {
	FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #f00; TEXT-DECORATION: =
underline
}
.moreArrow A:hover {
	FONT-WEIGHT: normal; FONT-SIZE: 11px; COLOR: #f00; TEXT-DECORATION: =
underline
}
#bannerBodySeminars {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/banner-seminars.jpg); WIDTH: =
731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyAbout {
	MIN-HEIGHT: 173px; FLOAT: left; BACKGROUND-IMAGE: =
url(/images/banner-about.jpg); WIDTH: 731px; BACKGROUND-REPEAT: =
no-repeat
}
#bannerBodyRails {
	MIN-HEIGHT: 173px; FLOAT: left; BACKGROUND-IMAGE: =
url(/images/category-banner.jpg); WIDTH: 731px; BACKGROUND-REPEAT: =
no-repeat
}
#banner {
	FLOAT: left
}
#bannerBodyContent {
	PADDING-RIGHT: 0px; PADDING-LEFT: 18px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
#bannerBodyContentLeftPad {
	PADDING-RIGHT: 0px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 0px
}
#bannerBodyContentRightPad {
	PADDING-RIGHT: 250px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 0px
}
#bannerBodyContentRightPadList {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; WIDTH: 300px; PADDING-TOP: 0px
}
#bannerFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/banner-foot.jpg); MARGIN: =
0px; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 10px
}
#bannerFootCategory {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/category-banner-foot.jpg); =
MARGIN: 0px; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 6px
}
#banner H1 {
	FONT-WEIGHT: bold; FONT-SIZE: 28px; MARGIN-BOTTOM: 10px; COLOR: #333; =
FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
#banner H2 {
	FONT-WEIGHT: bold; FONT-SIZE: 18px; COLOR: #474646; FONT-FAMILY: =
Verdana, Arial, Helvetica, sans-serif
}
#banner H3 {
	FONT-WEIGHT: normal; FONT-SIZE: 14px; COLOR: #333; FONT-FAMILY: =
Verdana, Arial, Helvetica, sans-serif
}
#banner LI LI {
	FONT-SIZE: 7px; LINE-HEIGHT: 7px
}
#banner P {
	FONT-SIZE: 12px; COLOR: #474646
}
#breakoutContainerSeminars {
	FLOAT: right; WIDTH: 212px
}
#breakoutBodySeminars {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/seminarpromo.jpg); WIDTH: =
212px; BACKGROUND-REPEAT: no-repeat
}
#breakoutBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 7px
}
#breakoutFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/breakout-bottom.jpg); =
MARGIN: 0px; WIDTH: 212px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 10px
}
#nakedContainerRightCol {
	MARGIN-TOP: 0px; FLOAT: right; WIDTH: 212px
}
#nakedBodyRightCol {
	FLOAT: left; WIDTH: 212px
}
#nakedBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 7px
}
#leftSubColContainer {
	FLOAT: left; MARGIN: 0px; WIDTH: 217px
}
#leftSubColBody {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/left-sub-col-bg-seminars.jpg); WIDTH: 217px; =
BACKGROUND-REPEAT: no-repeat
}
#leftSubColBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
#leftSubColFoot {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/left-sub-col-foot-seminars.jpg); MARGIN: 0px; WIDTH: 217px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 179px
}
#rightSubColContainer {
	FLOAT: right; WIDTH: 498px
}
#rightSubColBody {
	MIN-HEIGHT: 737px; FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right-sub-col-seminars.jpg); WIDTH: 498px; =
BACKGROUND-REPEAT: no-repeat
}
#rightSubColBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
#rightSubColFoot {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right-sub-col-foot-seminars.jpg); MARGIN: 0px; WIDTH: 498px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 12px
}
#subColContainer {
	FLOAT: left; WIDTH: 731px
}
#subColBody {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/sub-col-bg.jpg); WIDTH: =
731px; BACKGROUND-REPEAT: no-repeat
}
#subColBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
#subColFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/sub-col-foot.jpg); MARGIN: =
0px; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 137px
}
#rightColContainer {
	FLOAT: right; WIDTH: 212px
}
#rightColContainerFullCol {
	FLOAT: right; WIDTH: 212px
}
#rightColContainer {
	MARGIN-TOP: 22px
}
#rightColContainerFullCol {
	MARGIN-TOP: 0px
}
#rightColBody {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right/right-col-bg-blank.jpg); WIDTH: 212px; =
BACKGROUND-REPEAT: no-repeat
}
#rightColBodyUserComments {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/user-comments-bg.jpg); =
WIDTH: 212px; BACKGROUND-REPEAT: no-repeat
}
#rightColBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
#rightColFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/right/right-col-foot.jpg); =
MARGIN: 0px; WIDTH: 212px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 11px
}
#rightColFootUserComments {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/user-comments-foot.jpg); =
MARGIN: 0px; WIDTH: 212px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 10px
}
#rightColBodyTrainTall {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right/right-col-bg-train-bridge-tall.jpg); WIDTH: 212px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 779px
}
#rightColBodyTrainTallFull {
	MARGIN-TOP: -37px; FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right/right-col-bg-train-bridge-tall.jpg); WIDTH: 212px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 779px
}
#rightColBodyTrainShort {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right/right-col-bg-train-bridge-short.jpg); WIDTH: 212px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 497px
}
#rightColBodyCraneShort {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right/right-col-bg-crane-pages-short.jpg); WIDTH: 212px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 619px
}
#footer {
	CLEAR: both; HEIGHT: 30px
}
#footerContainer {
	FLOAT: right; MARGIN: 12px
}
.leftFoot {
	MARGIN-TOP: 12px; FLOAT: left; POSITION: relative
}
.rightFoot {
	MARGIN-TOP: 12px; DISPLAY: inline; FLOAT: right; POSITION: relative; =
TEXT-ALIGN: right
}
.clearfix:unknown {
	CLEAR: both; DISPLAY: block; VISIBILITY: hidden; HEIGHT: 0px; content: =
"."
}
.clearfix {
	DISPLAY: inline-block
}
* HTML .clearfix {
	HEIGHT: 1%
}
.clearfix {
	DISPLAY: block
}

@media Print   =20
{
#rightCol {
	DISPLAY: none
}
#leftCol {
	FLOAT: none; WIDTH: 100%
}
    }
#rightColContainerFullCol {
	FLOAT: right; MARGIN: 0px; WIDTH: 212px
}
#rightColBodyBanner1 {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/right-col-banner1.jpg); =
WIDTH: 212px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 779px
}
#rightColBodyBanner2 {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/right-col-banner2.jpg); =
WIDTH: 212px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 779px
}
#rightColBodyBannerShort {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/right-col-banner3.jpg); =
WIDTH: 212px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 619px
}
#rightSubColBodyGeneric {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/right-sub-col-generic.jpg); =
WIDTH: 498px; BACKGROUND-REPEAT: no-repeat
}
#rightSubColFootCrane {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right-sub-col-foot-crane.jpg); MARGIN: 0px; WIDTH: 498px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 121px
}
#rightSubColFootTrain {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right-sub-col-foot-train.jpg); MARGIN: 0px; WIDTH: 498px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 121px
}
#rightSubColFootCity {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/right-sub-col-foot-city.jpg); MARGIN: 0px; WIDTH: 498px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 121px
}
#leftSubColFootGeneric {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/left-sub-col-foot-generic.jpg); MARGIN: 0px; WIDTH: 217px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 11px
}
#leftSubColFootCity {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/left-sub-col-foot-city.jpg); =
MARGIN: 0px; WIDTH: 217px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 103px
}
#leftSubColFootCrane {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/left-sub-col-foot-crane.jpg); MARGIN: 0px; WIDTH: 217px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 103px
}
#leftSubColFootTrain {
	FLOAT: left; BACKGROUND-IMAGE: =
url(/images/left-sub-col-foot-train.jpg); MARGIN: 0px; WIDTH: 217px; =
BACKGROUND-REPEAT: no-repeat; HEIGHT: 103px
}
PRE {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
FORM {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
FIELDSET {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
INPUT {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px
}
IMG {
	BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: =
0px; BORDER-RIGHT-WIDTH: 0px
}
#navList {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none
}
#navList LI {
	DISPLAY: inline; FONT-SIZE: 11px; LIST-STYLE-TYPE: none
}
.imgVertAlign {
	VERTICAL-ALIGN: middle
}
.hrImgVertAlign {
	MARGIN: -10px 0px 5px
}
.rePositionGraphicTop1 {
	MARGIN-TOP: -4px; FLOAT: right; POSITION: relative
}
.formButton {
	MARGIN-TOP: -10px
}
#nav {
	FONT-SIZE: 11px; FLOAT: left; LINE-HEIGHT: normal
}
#nav UL {
	MARGIN: 0px; PADDING-TOP: 7px; LIST-STYLE-TYPE: none
}
#nav LI {
	PADDING-RIGHT: 1px; PADDING-LEFT: 9px; BACKGROUND: =
url(/images/tabs-left.gif) no-repeat left top; FLOAT: left; =
PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
#nav A {
	PADDING-RIGHT: 15px; DISPLAY: block; PADDING-LEFT: 6px; FONT-WEIGHT: =
bold; BACKGROUND: url(/images/tabs-right.gif) no-repeat right top; =
FLOAT: left; PADDING-BOTTOM: 4px; WIDTH: 0.1em; COLOR: #666; =
PADDING-TOP: 5px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; =
WHITE-SPACE: nowrap; TEXT-DECORATION: none
}
#nav > UL A {
	WIDTH: auto
}
#nav A:hover {
	COLOR: #719171
}
#nav LI:hover {
	BACKGROUND-POSITION: 0% -150px; COLOR: #fff
}
#nav LI:hover A {
	BACKGROUND-POSITION: 0% -150px; COLOR: #fff
}
#nav LI:hover A {
	BACKGROUND-POSITION: 100% -150px
}
#seminarsHome #nav-seminars {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#blogHome #nav-blog {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#rubyHome #nav-ruby {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#interfaceHome #nav-interface {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#serversHome #nav-servers {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#developmentHome #nav-development {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#seminarsHome #nav-seminars A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#blogHome #nav-blog A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#rubyHome #nav-ruby A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#interfaceHome #nav-interface A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#serversHome #nav-servers A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#developmentHome #nav-development A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#subNav {
	FONT-SIZE: 11px; FLOAT: right; LINE-HEIGHT: normal; POSITION: relative
}
#subNav UL {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none
}
#subNav LI {
	PADDING-RIGHT: 1px; PADDING-LEFT: 9px; BACKGROUND: =
url(/images/subnav-tabs-left.gif) no-repeat left top; FLOAT: left; =
PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
#subNav A {
	PADDING-RIGHT: 15px; DISPLAY: block; PADDING-LEFT: 6px; FONT-WEIGHT: =
bold; BACKGROUND: url(/images/subnav-tabs-right.gif) no-repeat right =
top; FLOAT: left; PADDING-BOTTOM: 10px; WIDTH: 0.1em; COLOR: #fff; =
PADDING-TOP: 10px; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; =
WHITE-SPACE: nowrap; TEXT-DECORATION: underline
}
#subNav > UL A {
	WIDTH: auto
}
#subNav A:hover {
	COLOR: #d32705; TEXT-DECORATION: none
}
#subNav LI:hover {
	BACKGROUND-POSITION: 0% -150px; COLOR: #d32705; TEXT-DECORATION: none
}
#subNav LI:hover A {
	BACKGROUND-POSITION: 0% -150px; COLOR: #d32705; TEXT-DECORATION: none
}
#subNav LI:hover A {
	BACKGROUND-POSITION: 100% -150px; TEXT-DECORATION: none
}
#subNav #subnav_current {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#subnav_current A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #d32705; TEXT-DECORATION: none
}
#nav #current {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#current A {
	BACKGROUND-POSITION: 100% -150px; COLOR: white; TEXT-DECORATION: none
}
.spacer1px {
	FONT-SIZE: 1px; LINE-HEIGHT: 1px
}
.spacer2px {
	FONT-SIZE: 2px; LINE-HEIGHT: 2px
}
.spacer3px {
	FONT-SIZE: 3px; LINE-HEIGHT: 3px
}
.spacer4px {
	FONT-SIZE: 4px; LINE-HEIGHT: 4px
}
.spacer5px {
	FONT-SIZE: 5px; LINE-HEIGHT: 5px
}
.spacer6px {
	FONT-SIZE: 6px; LINE-HEIGHT: 6px
}
.spacer7px {
	FONT-SIZE: 7px; LINE-HEIGHT: 7px
}
.spacer9px {
	FONT-SIZE: 9px; LINE-HEIGHT: 9px
}
.spacer10px {
	FONT-SIZE: 10px; LINE-HEIGHT: 10px
}
.spacer11px {
	FONT-SIZE: 11px; LINE-HEIGHT: 11px
}
.spacer13px {
	FONT-SIZE: 13px; LINE-HEIGHT: 13px
}
.spacer14px {
	FONT-SIZE: 14px; LINE-HEIGHT: 14px
}
.spacer15px {
	FONT-SIZE: 15px; LINE-HEIGHT: 15px
}
.spacer16px {
	FONT-SIZE: 16px; LINE-HEIGHT: 16px
}
.spacer17px {
	FONT-SIZE: 17px; LINE-HEIGHT: 17px
}
.spacer21px {
	FONT-SIZE: 21px; LINE-HEIGHT: 21px
}
.spacer28px {
	FONT-SIZE: 28px; LINE-HEIGHT: 28px
}
.spacer30px {
	FONT-SIZE: 30px; LINE-HEIGHT: 30px
}
.spacer35px {
	FONT-SIZE: 35px; LINE-HEIGHT: 35px
}
.spacer40px {
	FONT-SIZE: 40px; LINE-HEIGHT: 40px
}
.spacer80px {
	FONT-SIZE: 80px; LINE-HEIGHT: 80px
}
.spacer120px {
	FONT-SIZE: 120px; LINE-HEIGHT: 120px
}
.flash_notice_bar {
	PADDING-RIGHT: 10px; PADDING-LEFT: 10px; BACKGROUND: #fcc5bc; =
PADDING-BOTTOM: 10px; MARGIN: 0px auto 10px; WIDTH: 930px; PADDING-TOP: =
10px
}

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/stylesheets/append.css?1209768151

.fontBreakoutTitle {
	MARGIN-TOP: 0px; FONT-WEIGHT: bold; FONT-SIZE: 16px; MARGIN-BOTTOM: =
8px; COLOR: #fff; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
.fontBreakoutTitle A {
	MARGIN-TOP: 0px; FONT-WEIGHT: bold; FONT-SIZE: 16px; MARGIN-BOTTOM: =
8px; COLOR: #fff; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
.fontBreakoutTitle A {
	FONT-WEIGHT: bold; TEXT-DECORATION: none
}
LABEL.left {
	PADDING-RIGHT: 8px! important; FLOAT: left; VERTICAL-ALIGN: middle! =
important; WIDTH: 90px; TEXT-ALIGN: right! important
}
LABEL.left_narrow {
	PADDING-RIGHT: 8px! important; FONT-SIZE: 12px! important; FLOAT: left; =
VERTICAL-ALIGN: middle! important; WIDTH: 62px; TEXT-ALIGN: right! =
important
}
.fieldWithErrors INPUT {
	BACKGROUND-COLOR: #fcc
}
.fieldWithErrors TEXTAREA {
	BACKGROUND-COLOR: #fcc
}
.fieldWithErrors SELECT {
	BACKGROUND-COLOR: #fcc
}
DIV.fieldWithErrors {
	DISPLAY: inline! important
}
#errorExplanation {
	BORDER-RIGHT: #c00 2px solid; BORDER-TOP: #c00 2px solid; =
MARGIN-BOTTOM: 20px; PADDING-BOTTOM: 12px; BORDER-LEFT: #c00 2px solid; =
WIDTH: 90%; BORDER-BOTTOM: #c00 2px solid
}
#errorExplanation H2 {
	PADDING-RIGHT: 5px; PADDING-LEFT: 15px; FONT-WEIGHT: bold; FONT-SIZE: =
14px; PADDING-BOTTOM: 5px; MARGIN: 0px; COLOR: #fff; PADDING-TOP: 5px; =
BACKGROUND-COLOR: #c00; TEXT-ALIGN: left
}
#errorExplanation P {
	PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-WEIGHT: bold; =
MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 5px; PADDING-TOP: 5px
}
#errorExplanation UL LI {
	FONT-SIZE: 12px; LIST-STYLE-TYPE: square
}
.reqd {
	FONT-WEIGHT: bold! important
}
.indent {
	MARGIN-LEFT: 98px
}
#bigColumn {
	FLOAT: left; WIDTH: 731px
}
#bigColumnContent {
	PADDING-RIGHT: 0px; PADDING-LEFT: 18px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
H2 {
	FONT-WEIGHT: bold
}
H2.h2TightMargin {
	FONT-WEIGHT: bold
}
#subColNoBanner {
	FLOAT: left; WIDTH: 731px; POSITION: relative; TEXT-ALIGN: left
}
.fontBannerSubhead {
	FONT-WEIGHT: bold; FONT-SIZE: 14px; COLOR: #474646; FONT-FAMILY: =
Verdana, Arial, Helvetica, sans-serif
}
#home #nav-home {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#podcast #nav-podcast {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#articles #nav-articles {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#admin #nav-admin {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#books #nav-books {
	BORDER-TOP-WIDTH: 0px; BACKGROUND-POSITION: 0px -150px; =
BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: =
0px
}
#home #nav-home A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#podcast #nav-podcast A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#articles #nav-articles A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#admin #nav-admin A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#books #nav-books A {
	BACKGROUND-POSITION: 100% -150px; COLOR: #fff
}
#breakoutBodyContent P {
	COLOR: white
}
#breakoutBodyContent A {
	COLOR: white
}
#breakoutBodyContent H2 {
	COLOR: white
}
#breakoutBodyContent A {
	TEXT-DECORATION: none
}
#breakoutBodyContent H2 A {
	FONT-WEIGHT: bold; FONT-SIZE: 18px
}
.moreInfo {
	FONT-WEIGHT: bold; COLOR: white; TEXT-DECORATION: underline
}
.section_head_expanded {
	PADDING-LEFT: 20px! important; BACKGROUND: url(/images/expanded.gif) =
no-repeat left center; PADDING-BOTTOM: 0px! important; MARGIN: 0px 0px =
-8px; CURSOR: pointer
}
.section_head_collapsed {
	PADDING-LEFT: 20px! important; BACKGROUND: url(/images/collapsed.gif) =
no-repeat left center; PADDING-BOTTOM: 6px! important; MARGIN: 0px; =
CURSOR: pointer; PADDING-TOP: 0px! important
}
.mini_comment {
	BORDER-RIGHT: #999 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: #999 1px =
solid; MARGIN-TOP: 10px; PADDING-LEFT: 10px; MARGIN-BOTTOM: 10px; =
PADDING-BOTTOM: 5px; BORDER-LEFT: #999 1px solid; PADDING-TOP: 5px; =
BORDER-BOTTOM: #999 1px solid; BACKGROUND-COLOR: #eee
}
.mini_comment .mini_title {
	FONT-WEIGHT: bold
}
.mini_comment .mini_author {
	FONT-STYLE: italic
}
.mini_comment .mini_body {
=09
}
#suggestion_errors #errorExplanation {
	BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: =
none; BORDER-BOTTOM-STYLE: none
}
#suggestion_errors #errorExplanation H2 {
	DISPLAY: none
}
#suggestion_errors #errorExplanation UL LI {
	FONT-WEIGHT: bold; COLOR: red
}
PRE {
	PADDING-RIGHT: 8px; PADDING-LEFT: 8px; FONT-SIZE: 12px; BACKGROUND: =
#eee; OVERFLOW-X: auto; PADDING-BOTTOM: 8px; MARGIN: 0.8em 0px; WIDTH: =
98%; LINE-HEIGHT: 130%; PADDING-TOP: 8px; FONT-FAMILY: courier; =
whitespace: nowrap
}
CODE {
	FONT-FAMILY: courier
}
.biglink {
	FONT-SIZE: 20px! important
}
.bigLink A {
	FONT-SIZE: 20px! important
}
.bigLink A:link {
	FONT-SIZE: 20px! important
}
.bigLink A:hover {
	FONT-SIZE: 20px! important
}
.bigLink A:visited {
	FONT-SIZE: 20px! important
}
.bigLink A:active {
	FONT-SIZE: 20px! important
}
.linkList P {
	MARGIN: 0px; FONT-STYLE: italic
}
.linkList LI A {
	FONT-SIZE: 12px
}
.linkList LI {
	PADDING-TOP: 4px
}
.bookList H3 {
	FONT-WEIGHT: bold
}
.bookList P.author {
	FONT-STYLE: italic
}
.bookList A:link {
	COLOR: #333; TEXT-DECORATION: none
}
.bookList A:visited {
	COLOR: #333; TEXT-DECORATION: none
}
.bookList A:hover {
	COLOR: #666; TEXT-DECORATION: underline
}
#podcast_box {
=09
}
#podcast_player {
	FLOAT: right; PADDING-BOTTOM: 5px; WIDTH: 260px
}
#podcast_player OBJECT {
	MARGIN-TOP: 0px
}
#podcast_player EMBED {
	MARGIN-TOP: 0px
}
#podcast_playlabel {
	FONT-SIZE: 11px; COLOR: #bb0d04
}
#podcast_info {
=09
}
.affiliate_ad {
	PADDING-RIGHT: 10px; FLOAT: left; PADDING-BOTTOM: 10px
}
.ad_code {
	BORDER-RIGHT: black 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: black =
1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; BORDER-LEFT: black =
1px solid; PADDING-TOP: 10px; BORDER-BOTTOM: black 1px solid
}
.banner_body {
	WIDTH: 250px
}
#left_col {
	BORDER-RIGHT: #b0aba3 1px solid; PADDING-RIGHT: 10px; PADDING-LEFT: =
0px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 46%; =
PADDING-TOP: 0px
}
#right_col {
	PADDING-RIGHT: 0px; PADDING-LEFT: 9px; FLOAT: right; PADDING-BOTTOM: =
0px; MARGIN: 0px; WIDTH: 48%; PADDING-TOP: 0px
}
#bannerBodySeminars {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyAbout {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyArticles {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyDevelopment {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyHome {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyPodcast {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyRails {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyServers {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodyUI {
	FLOAT: left; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat
}
#bannerBodySeminars {
	BACKGROUND-IMAGE: url(/images/banners/seminar.jpg)
}
#bannerBodyAbout {
	BACKGROUND-IMAGE: url(/images/banners/aboutus.jpg)
}
#bannerBodyArticles {
	BACKGROUND-IMAGE: url(/images/banners/articles.jpg)
}
#bannerBodyDevelopment {
	BACKGROUND-IMAGE: url(/images/banners/category-development.jpg)
}
#bannerBodyHome {
	BACKGROUND-IMAGE: url(/images/banners/homepage.jpg)
}
#bannerBodyPodcast {
	BACKGROUND-IMAGE: url(/images/banners/podcast.jpg)
}
#bannerBodyServers {
	BACKGROUND-IMAGE: url(/images/banners/category-servers.jpg)
}
#bannerBodyUI {
	BACKGROUND-IMAGE: url(/images/banners/category-userinterface.jpg)
}
#bannerBodyBusiness {
	BACKGROUND-IMAGE: url(/images/banners/category-business.jpg)
}
#bannerFoot {
	FLOAT: left; BACKGROUND-IMAGE: url(/images/banners/banner-footer.jpg); =
MARGIN: 0px; WIDTH: 731px; BACKGROUND-REPEAT: no-repeat; HEIGHT: 10px
}
#bannerBodyContent {
	MIN-HEIGHT: 215px
}
#rightColBodyContent {
	PADDING-RIGHT: 16px; PADDING-LEFT: 16px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 16px
}
#rightColContainerTop {
	MARGIN-TOP: 0px; FLOAT: right; WIDTH: 212px
}
#article_body {
	MARGIN-LEFT: 10px; MARGIN-RIGHT: 10px
}
#article_body H1 {
	FONT-WEIGHT: bold; FONT-SIZE: 24px; MARGIN-LEFT: 0px
}
#article_body H2 {
	MARGIN-BOTTOM: 15px; MARGIN-LEFT: 0px
}
#article_body P {
	LINE-HEIGHT: 170%
}
#article_body UL LI {
	LINE-HEIGHT: 170%
}
#article_body OL LI {
	LINE-HEIGHT: 170%
}
#nav A {
	FONT-SIZE: 11px
}
P.sub_nav {
	FONT-WEIGHT: bold
}
#inline_search_box {
	MARGIN-TOP: 12px; PADDING-LEFT: 5px; FLOAT: right
}
.author {
	MARGIN-TOP: 0px; FONT-SIZE: 12px; MARGIN-BOTTOM: 0px; FONT-STYLE: =
italic
}
.description {
	MARGIN-TOP: 0px; FONT-SIZE: 12px; MARGIN-BOTTOM: 0px; FONT-STYLE: =
normal
}
#banner .more_head {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; =
PADDING-TOP: 15px
}
#banner_more {
	PADDING-RIGHT: 10px; MARGIN-TOP: 190px; FLOAT: right; WIDTH: 290px
}
#banner_more H2 {
	FONT-WEIGHT: bold; FONT-SIZE: 16px; MARGIN: 0px 0px 0.7em; COLOR: #333; =
FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
.article_excerpt H2 A:link {
	COLOR: #333; TEXT-DECORATION: none
}
.article_excerpt H2 A:visited {
	COLOR: #333; TEXT-DECORATION: none
}
.article_excerpt H2 A:active {
	COLOR: #333; TEXT-DECORATION: none
}
.article_excerpt H2 A:hover {
	COLOR: #666; TEXT-DECORATION: underline
}
.bucket .article_excerpt H4 {
	FONT-WEIGHT: bold! important; FONT-SIZE: 12px! important; =
MARGIN-BOTTOM: 0px! important
}
#browserNaviCenter {
	PADDING-RIGHT: 4px; PADDING-LEFT: 4px; BACKGROUND-IMAGE: =
url(/images/naviSlice.jpg); BACKGROUND-REPEAT: repeat-x; HEIGHT: 21px; =
BACKGROUND-COLOR: #fff
}
#browserNaviItem {
	FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #fff; PADDING-TOP: 4px; =
TEXT-DECORATION: none
}
#browserNaviItem A:link {
	FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #fff; PADDING-TOP: 4px; =
TEXT-DECORATION: none
}
#browserNaviItem A:visited {
	FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #fff; PADDING-TOP: 4px; =
TEXT-DECORATION: none
}
#browserNaviItem A:hover {
	FONT-WEIGHT: bold; FONT-SIZE: 10px; COLOR: #fff; PADDING-TOP: 4px; =
TEXT-DECORATION: none
}
.browserNaviNotSelected {
	MARGIN-TOP: 2px; FONT-SIZE: 11px; MARGIN-LEFT: 2px; COLOR: #bb0d04; =
HEIGHT: 16px; BACKGROUND-COLOR: #fff; TEXT-DECORATION: none
}
.browserNaviNotSelected A:link {
	MARGIN-TOP: 2px; FONT-SIZE: 11px; MARGIN-LEFT: 2px; COLOR: #bb0d04; =
HEIGHT: 16px; BACKGROUND-COLOR: #fff; TEXT-DECORATION: none
}
.browserNaviNotSelected A:visited {
	MARGIN-TOP: 2px; FONT-SIZE: 11px; MARGIN-LEFT: 2px; COLOR: #bb0d04; =
HEIGHT: 16px; BACKGROUND-COLOR: #fff; TEXT-DECORATION: none
}
.browserNaviNotSelected A:hover {
	COLOR: #f00
}
.tagline {
	FONT-WEIGHT: bold; FONT-SIZE: 14px; COLOR: #bb0d04
}
.betaLabel {
	FONT-WEIGHT: bold; FONT-SIZE: 28px; COLOR: #fdd
}
.logo {
	FONT-WEIGHT: bold; FONT-SIZE: 40px! important; WIDTH: 700px! important; =
FONT-FAMILY: Verdana; LETTER-SPACING: -2px; TEXT-DECORATION: none
}
.logo_red {
	COLOR: #bb0d04
}
.logo_black {
	COLOR: #333
}
.logo A:link {
	TEXT-DECORATION: none
}
.logo A:hover {
	TEXT-DECORATION: none
}
.logo A:visited {
	TEXT-DECORATION: none
}
.logo A:active {
	TEXT-DECORATION: none
}
.sidebarHead {
	FONT-WEIGHT: bold; FONT-SIZE: 18px; COLOR: #333
}
.inplaceeditor-form TEXTAREA {
	WIDTH: 400px
}
.book_title {
=09
}
#form_email {
	DISPLAY: none
}
.mini_label {
	CLEAR: left; DISPLAY: block; FLOAT: left; WIDTH: 50px
}
.odd {
	BACKGROUND-COLOR: #eee
}
.even {
	BACKGROUND-COLOR: #ddd
}
.odd TD {
	PADDING-BOTTOM: 4px; PADDING-TOP: 4px
}
.even TD {
	PADDING-BOTTOM: 4px; PADDING-TOP: 4px
}
A.book_button {
	BORDER-RIGHT: #bb0d04 2px solid; PADDING-RIGHT: 4px; BORDER-TOP: =
#bb0d04 1px solid; PADDING-LEFT: 4px; FONT-WEIGHT: bold; PADDING-BOTTOM: =
4px; BORDER-LEFT: #bb0d04 1px solid; PADDING-TOP: 4px; BORDER-BOTTOM: =
#bb0d04 2px solid; TEXT-DECORATION: none
}
A.book_button:hover {
	COLOR: white; BACKGROUND-COLOR: #bb0d04; TEXT-DECORATION: none
}
#new_comment_div {
	PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: =
10px 0px; PADDING-TOP: 10px; BACKGROUND-COLOR: #ddd; outline: 1px solid =
#999
}

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/stylesheets/treeview-menu.css?1209768151

.ygtvtn {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -5px -240px; WIDTH: =
1em; HEIGHT: 20px
}
.ygtvtm {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px 2px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvtmh {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px -77px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvtp {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px -315px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvtph {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px -395px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvln {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -5px -240px; WIDTH: =
1em; HEIGHT: 20px
}
.ygtvlm {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px 2px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvlmh {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px -77px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvlp {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px -315px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvlph {
	BACKGROUND: url(/images/sprite-menu.gif) no-repeat -8px -395px; WIDTH: =
1em; CURSOR: pointer; HEIGHT: 20px
}
.ygtvloading {
	BACKGROUND: url(/images/treeview-loading.gif) no-repeat 0px 0px; WIDTH: =
1em; HEIGHT: 20px
}
.ygtvdepthcell {
	BACKGROUND: none transparent scroll repeat 0% 0%; WIDTH: 1em; HEIGHT: =
20px
}
.ygtvblankdepthcell {
	WIDTH: 1em; HEIGHT: 20px
}
.ygtvitem {
=09
}
.ygtvchildren {
=09
}
* HTML .ygtvchildren {
	HEIGHT: 2%
}
.ygtvlabel {
	FONT-SIZE: 11px; MARGIN-LEFT: 2px; BACKGROUND-COLOR: white; =
TEXT-DECORATION: none
}
.ygtvlabel:link {
	FONT-SIZE: 11px; MARGIN-LEFT: 2px; BACKGROUND-COLOR: white; =
TEXT-DECORATION: none
}
.ygtvlabel:visited {
	FONT-SIZE: 11px; MARGIN-LEFT: 2px; BACKGROUND-COLOR: white; =
TEXT-DECORATION: none
}
.ygtvlabel:hover {
	FONT-SIZE: 11px; MARGIN-LEFT: 2px; BACKGROUND-COLOR: white; =
TEXT-DECORATION: none
}
.ygtvlabelactive {
	BACKGROUND-COLOR: yellow
}
.ygtvspacer {
	WIDTH: 1em; HEIGHT: 20px
}

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/stylesheets/stars.css?1209768151

DIV.starry {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; WIDTH: auto; PADDING-TOP: 0px
}
DIV.standard_star {
	DISPLAY: inline; FLOAT: left; CURSOR: pointer; BACKGROUND-REPEAT: =
no-repeat
}
DIV.feedback {
	BORDER-RIGHT: #ddd 1px solid; PADDING-RIGHT: 3px; BORDER-TOP: #ddd 1px =
solid; DISPLAY: inline; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; =
BORDER-LEFT: #ddd 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #ddd 1px =
solid
}

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/stylesheets/print.css?1209768151

#header {
	DISPLAY: none
}
#right_col {
	DISPLAY: none
}
#rightCol {
	DISPLAY: none
}
.noprint {
	DISPLAY: none
}
#breakoutBodySeminars {
	DISPLAY: none
}
HTML {
	BACKGROUND: white; BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; =
BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
}
BODY {
	FONT-SIZE: 10pt! important; COLOR: black
}
TD {
	FONT-SIZE: 10pt! important; COLOR: black
}
TH {
	FONT-SIZE: 10pt! important; COLOR: black
}
P {
	FONT-SIZE: 10pt! important; COLOR: black
}
LABEL {
	FONT-SIZE: 10pt! important; COLOR: black
}
LEGEND {
	FONT-SIZE: 10pt! important; COLOR: black
}
DD {
	FONT-SIZE: 10pt! important; COLOR: black
}
DT {
	FONT-SIZE: 10pt! important; COLOR: black
}
UL {
	FONT-SIZE: 10pt! important; COLOR: black
}
OL {
	FONT-SIZE: 10pt! important; COLOR: black
}
LI {
	FONT-SIZE: 10pt! important; COLOR: black
}
H1 {
	FONT-SIZE: 14pt
}
H2 {
	FONT-SIZE: 12pt
}
H3 {
	FONT-SIZE: 11pt
}
#pagewrapper {
	WIDTH: 95%; BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; =
BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none
}
#lefthalf {
	WIDTH: 49%
}
#righthalf {
	WIDTH: 49%
}
#footer {
	CLEAR: both
}
#footer P {
	FONT-SIZE: 10pt; COLOR: black
}
#footer A {
	FONT-SIZE: 10pt; COLOR: black
}
.article {
	MARGIN-LEFT: 0px! important; WIDTH: 95%! important
}
.article #right_col {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: =
0px; WIDTH: 770px; PADDING-TOP: 0px
}
#related #left_col {
	DISPLAY: none; WIDTH: 0px
}
.noprint {
	DISPLAY: none
}

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/prototype.js?1209768151

/*  Prototype JavaScript framework, version 1.5.0=0A=
 *  (c) 2005-2007 Sam Stephenson=0A=
 *=0A=
 *  Prototype is freely distributable under the terms of an MIT-style =
license.=0A=
 *  For details, see the Prototype web site: http://prototype.conio.net/=0A=
 *=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
var Prototype =3D {=0A=
  Version: '1.5.0',=0A=
  BrowserFeatures: {=0A=
    XPath: !!document.evaluate=0A=
  },=0A=
=0A=
  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',=0A=
  emptyFunction: function() {},=0A=
  K: function(x) { return x }=0A=
}=0A=
=0A=
var Class =3D {=0A=
  create: function() {=0A=
    return function() {=0A=
      this.initialize.apply(this, arguments);=0A=
    }=0A=
  }=0A=
}=0A=
=0A=
var Abstract =3D new Object();=0A=
=0A=
Object.extend =3D function(destination, source) {=0A=
  for (var property in source) {=0A=
    destination[property] =3D source[property];=0A=
  }=0A=
  return destination;=0A=
}=0A=
=0A=
Object.extend(Object, {=0A=
  inspect: function(object) {=0A=
    try {=0A=
      if (object =3D=3D=3D undefined) return 'undefined';=0A=
      if (object =3D=3D=3D null) return 'null';=0A=
      return object.inspect ? object.inspect() : object.toString();=0A=
    } catch (e) {=0A=
      if (e instanceof RangeError) return '...';=0A=
      throw e;=0A=
    }=0A=
  },=0A=
=0A=
  keys: function(object) {=0A=
    var keys =3D [];=0A=
    for (var property in object)=0A=
      keys.push(property);=0A=
    return keys;=0A=
  },=0A=
=0A=
  values: function(object) {=0A=
    var values =3D [];=0A=
    for (var property in object)=0A=
      values.push(object[property]);=0A=
    return values;=0A=
  },=0A=
=0A=
  clone: function(object) {=0A=
    return Object.extend({}, object);=0A=
  }=0A=
});=0A=
=0A=
Function.prototype.bind =3D function() {=0A=
  var __method =3D this, args =3D $A(arguments), object =3D args.shift();=0A=
  return function() {=0A=
    return __method.apply(object, args.concat($A(arguments)));=0A=
  }=0A=
}=0A=
=0A=
Function.prototype.bindAsEventListener =3D function(object) {=0A=
  var __method =3D this, args =3D $A(arguments), object =3D args.shift();=0A=
  return function(event) {=0A=
    return __method.apply(object, [( event || =
window.event)].concat(args).concat($A(arguments)));=0A=
  }=0A=
}=0A=
=0A=
Object.extend(Number.prototype, {=0A=
  toColorPart: function() {=0A=
    var digits =3D this.toString(16);=0A=
    if (this < 16) return '0' + digits;=0A=
    return digits;=0A=
  },=0A=
=0A=
  succ: function() {=0A=
    return this + 1;=0A=
  },=0A=
=0A=
  times: function(iterator) {=0A=
    $R(0, this, true).each(iterator);=0A=
    return this;=0A=
  }=0A=
});=0A=
=0A=
var Try =3D {=0A=
  these: function() {=0A=
    var returnValue;=0A=
=0A=
    for (var i =3D 0, length =3D arguments.length; i < length; i++) {=0A=
      var lambda =3D arguments[i];=0A=
      try {=0A=
        returnValue =3D lambda();=0A=
        break;=0A=
      } catch (e) {}=0A=
    }=0A=
=0A=
    return returnValue;=0A=
  }=0A=
}=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
var PeriodicalExecuter =3D Class.create();=0A=
PeriodicalExecuter.prototype =3D {=0A=
  initialize: function(callback, frequency) {=0A=
    this.callback =3D callback;=0A=
    this.frequency =3D frequency;=0A=
    this.currentlyExecuting =3D false;=0A=
=0A=
    this.registerCallback();=0A=
  },=0A=
=0A=
  registerCallback: function() {=0A=
    this.timer =3D setInterval(this.onTimerEvent.bind(this), =
this.frequency * 1000);=0A=
  },=0A=
=0A=
  stop: function() {=0A=
    if (!this.timer) return;=0A=
    clearInterval(this.timer);=0A=
    this.timer =3D null;=0A=
  },=0A=
=0A=
  onTimerEvent: function() {=0A=
    if (!this.currentlyExecuting) {=0A=
      try {=0A=
        this.currentlyExecuting =3D true;=0A=
        this.callback(this);=0A=
      } finally {=0A=
        this.currentlyExecuting =3D false;=0A=
      }=0A=
    }=0A=
  }=0A=
}=0A=
String.interpret =3D function(value){=0A=
  return value =3D=3D null ? '' : String(value);=0A=
}=0A=
=0A=
Object.extend(String.prototype, {=0A=
  gsub: function(pattern, replacement) {=0A=
    var result =3D '', source =3D this, match;=0A=
    replacement =3D arguments.callee.prepareReplacement(replacement);=0A=
=0A=
    while (source.length > 0) {=0A=
      if (match =3D source.match(pattern)) {=0A=
        result +=3D source.slice(0, match.index);=0A=
        result +=3D String.interpret(replacement(match));=0A=
        source  =3D source.slice(match.index + match[0].length);=0A=
      } else {=0A=
        result +=3D source, source =3D '';=0A=
      }=0A=
    }=0A=
    return result;=0A=
  },=0A=
=0A=
  sub: function(pattern, replacement, count) {=0A=
    replacement =3D this.gsub.prepareReplacement(replacement);=0A=
    count =3D count =3D=3D=3D undefined ? 1 : count;=0A=
=0A=
    return this.gsub(pattern, function(match) {=0A=
      if (--count < 0) return match[0];=0A=
      return replacement(match);=0A=
    });=0A=
  },=0A=
=0A=
  scan: function(pattern, iterator) {=0A=
    this.gsub(pattern, iterator);=0A=
    return this;=0A=
  },=0A=
=0A=
  truncate: function(length, truncation) {=0A=
    length =3D length || 30;=0A=
    truncation =3D truncation =3D=3D=3D undefined ? '...' : truncation;=0A=
    return this.length > length ?=0A=
      this.slice(0, length - truncation.length) + truncation : this;=0A=
  },=0A=
=0A=
  strip: function() {=0A=
    return this.replace(/^\s+/, '').replace(/\s+$/, '');=0A=
  },=0A=
=0A=
  stripTags: function() {=0A=
    return this.replace(/<\/?[^>]+>/gi, '');=0A=
  },=0A=
=0A=
  stripScripts: function() {=0A=
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');=0A=
  },=0A=
=0A=
  extractScripts: function() {=0A=
    var matchAll =3D new RegExp(Prototype.ScriptFragment, 'img');=0A=
    var matchOne =3D new RegExp(Prototype.ScriptFragment, 'im');=0A=
    return (this.match(matchAll) || []).map(function(scriptTag) {=0A=
      return (scriptTag.match(matchOne) || ['', ''])[1];=0A=
    });=0A=
  },=0A=
=0A=
  evalScripts: function() {=0A=
    return this.extractScripts().map(function(script) { return =
eval(script) });=0A=
  },=0A=
=0A=
  escapeHTML: function() {=0A=
    var div =3D document.createElement('div');=0A=
    var text =3D document.createTextNode(this);=0A=
    div.appendChild(text);=0A=
    return div.innerHTML;=0A=
  },=0A=
=0A=
  unescapeHTML: function() {=0A=
    var div =3D document.createElement('div');=0A=
    div.innerHTML =3D this.stripTags();=0A=
    return div.childNodes[0] ? (div.childNodes.length > 1 ?=0A=
      $A(div.childNodes).inject('',function(memo,node){ return =
memo+node.nodeValue }) :=0A=
      div.childNodes[0].nodeValue) : '';=0A=
  },=0A=
=0A=
  toQueryParams: function(separator) {=0A=
    var match =3D this.strip().match(/([^?#]*)(#.*)?$/);=0A=
    if (!match) return {};=0A=
=0A=
    return match[1].split(separator || '&').inject({}, function(hash, =
pair) {=0A=
      if ((pair =3D pair.split('=3D'))[0]) {=0A=
        var name =3D decodeURIComponent(pair[0]);=0A=
        var value =3D pair[1] ? decodeURIComponent(pair[1]) : undefined;=0A=
=0A=
        if (hash[name] !=3D=3D undefined) {=0A=
          if (hash[name].constructor !=3D Array)=0A=
            hash[name] =3D [hash[name]];=0A=
          if (value) hash[name].push(value);=0A=
        }=0A=
        else hash[name] =3D value;=0A=
      }=0A=
      return hash;=0A=
    });=0A=
  },=0A=
=0A=
  toArray: function() {=0A=
    return this.split('');=0A=
  },=0A=
=0A=
  succ: function() {=0A=
    return this.slice(0, this.length - 1) +=0A=
      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);=0A=
  },=0A=
=0A=
  camelize: function() {=0A=
    var parts =3D this.split('-'), len =3D parts.length;=0A=
    if (len =3D=3D 1) return parts[0];=0A=
=0A=
    var camelized =3D this.charAt(0) =3D=3D '-'=0A=
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)=0A=
      : parts[0];=0A=
=0A=
    for (var i =3D 1; i < len; i++)=0A=
      camelized +=3D parts[i].charAt(0).toUpperCase() + =
parts[i].substring(1);=0A=
=0A=
    return camelized;=0A=
  },=0A=
=0A=
  capitalize: function(){=0A=
    return this.charAt(0).toUpperCase() + =
this.substring(1).toLowerCase();=0A=
  },=0A=
=0A=
  underscore: function() {=0A=
    return this.gsub(/::/, =
'/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{=
1}_#{2}').gsub(/-/,'_').toLowerCase();=0A=
  },=0A=
=0A=
  dasherize: function() {=0A=
    return this.gsub(/_/,'-');=0A=
  },=0A=
=0A=
  inspect: function(useDoubleQuotes) {=0A=
    var escapedString =3D this.replace(/\\/g, '\\\\');=0A=
    if (useDoubleQuotes)=0A=
      return '"' + escapedString.replace(/"/g, '\\"') + '"';=0A=
    else=0A=
      return "'" + escapedString.replace(/'/g, '\\\'') + "'";=0A=
  }=0A=
});=0A=
=0A=
String.prototype.gsub.prepareReplacement =3D function(replacement) {=0A=
  if (typeof replacement =3D=3D 'function') return replacement;=0A=
  var template =3D new Template(replacement);=0A=
  return function(match) { return template.evaluate(match) };=0A=
}=0A=
=0A=
String.prototype.parseQuery =3D String.prototype.toQueryParams;=0A=
=0A=
var Template =3D Class.create();=0A=
Template.Pattern =3D /(^|.|\r|\n)(#\{(.*?)\})/;=0A=
Template.prototype =3D {=0A=
  initialize: function(template, pattern) {=0A=
    this.template =3D template.toString();=0A=
    this.pattern  =3D pattern || Template.Pattern;=0A=
  },=0A=
=0A=
  evaluate: function(object) {=0A=
    return this.template.gsub(this.pattern, function(match) {=0A=
      var before =3D match[1];=0A=
      if (before =3D=3D '\\') return match[2];=0A=
      return before + String.interpret(object[match[3]]);=0A=
    });=0A=
  }=0A=
}=0A=
=0A=
var $break    =3D new Object();=0A=
var $continue =3D new Object();=0A=
=0A=
var Enumerable =3D {=0A=
  each: function(iterator) {=0A=
    var index =3D 0;=0A=
    try {=0A=
      this._each(function(value) {=0A=
        try {=0A=
          iterator(value, index++);=0A=
        } catch (e) {=0A=
          if (e !=3D $continue) throw e;=0A=
        }=0A=
      });=0A=
    } catch (e) {=0A=
      if (e !=3D $break) throw e;=0A=
    }=0A=
    return this;=0A=
  },=0A=
=0A=
  eachSlice: function(number, iterator) {=0A=
    var index =3D -number, slices =3D [], array =3D this.toArray();=0A=
    while ((index +=3D number) < array.length)=0A=
      slices.push(array.slice(index, index+number));=0A=
    return slices.map(iterator);=0A=
  },=0A=
=0A=
  all: function(iterator) {=0A=
    var result =3D true;=0A=
    this.each(function(value, index) {=0A=
      result =3D result && !!(iterator || Prototype.K)(value, index);=0A=
      if (!result) throw $break;=0A=
    });=0A=
    return result;=0A=
  },=0A=
=0A=
  any: function(iterator) {=0A=
    var result =3D false;=0A=
    this.each(function(value, index) {=0A=
      if (result =3D !!(iterator || Prototype.K)(value, index))=0A=
        throw $break;=0A=
    });=0A=
    return result;=0A=
  },=0A=
=0A=
  collect: function(iterator) {=0A=
    var results =3D [];=0A=
    this.each(function(value, index) {=0A=
      results.push((iterator || Prototype.K)(value, index));=0A=
    });=0A=
    return results;=0A=
  },=0A=
=0A=
  detect: function(iterator) {=0A=
    var result;=0A=
    this.each(function(value, index) {=0A=
      if (iterator(value, index)) {=0A=
        result =3D value;=0A=
        throw $break;=0A=
      }=0A=
    });=0A=
    return result;=0A=
  },=0A=
=0A=
  findAll: function(iterator) {=0A=
    var results =3D [];=0A=
    this.each(function(value, index) {=0A=
      if (iterator(value, index))=0A=
        results.push(value);=0A=
    });=0A=
    return results;=0A=
  },=0A=
=0A=
  grep: function(pattern, iterator) {=0A=
    var results =3D [];=0A=
    this.each(function(value, index) {=0A=
      var stringValue =3D value.toString();=0A=
      if (stringValue.match(pattern))=0A=
        results.push((iterator || Prototype.K)(value, index));=0A=
    })=0A=
    return results;=0A=
  },=0A=
=0A=
  include: function(object) {=0A=
    var found =3D false;=0A=
    this.each(function(value) {=0A=
      if (value =3D=3D object) {=0A=
        found =3D true;=0A=
        throw $break;=0A=
      }=0A=
    });=0A=
    return found;=0A=
  },=0A=
=0A=
  inGroupsOf: function(number, fillWith) {=0A=
    fillWith =3D fillWith =3D=3D=3D undefined ? null : fillWith;=0A=
    return this.eachSlice(number, function(slice) {=0A=
      while(slice.length < number) slice.push(fillWith);=0A=
      return slice;=0A=
    });=0A=
  },=0A=
=0A=
  inject: function(memo, iterator) {=0A=
    this.each(function(value, index) {=0A=
      memo =3D iterator(memo, value, index);=0A=
    });=0A=
    return memo;=0A=
  },=0A=
=0A=
  invoke: function(method) {=0A=
    var args =3D $A(arguments).slice(1);=0A=
    return this.map(function(value) {=0A=
      return value[method].apply(value, args);=0A=
    });=0A=
  },=0A=
=0A=
  max: function(iterator) {=0A=
    var result;=0A=
    this.each(function(value, index) {=0A=
      value =3D (iterator || Prototype.K)(value, index);=0A=
      if (result =3D=3D undefined || value >=3D result)=0A=
        result =3D value;=0A=
    });=0A=
    return result;=0A=
  },=0A=
=0A=
  min: function(iterator) {=0A=
    var result;=0A=
    this.each(function(value, index) {=0A=
      value =3D (iterator || Prototype.K)(value, index);=0A=
      if (result =3D=3D undefined || value < result)=0A=
        result =3D value;=0A=
    });=0A=
    return result;=0A=
  },=0A=
=0A=
  partition: function(iterator) {=0A=
    var trues =3D [], falses =3D [];=0A=
    this.each(function(value, index) {=0A=
      ((iterator || Prototype.K)(value, index) ?=0A=
        trues : falses).push(value);=0A=
    });=0A=
    return [trues, falses];=0A=
  },=0A=
=0A=
  pluck: function(property) {=0A=
    var results =3D [];=0A=
    this.each(function(value, index) {=0A=
      results.push(value[property]);=0A=
    });=0A=
    return results;=0A=
  },=0A=
=0A=
  reject: function(iterator) {=0A=
    var results =3D [];=0A=
    this.each(function(value, index) {=0A=
      if (!iterator(value, index))=0A=
        results.push(value);=0A=
    });=0A=
    return results;=0A=
  },=0A=
=0A=
  sortBy: function(iterator) {=0A=
    return this.map(function(value, index) {=0A=
      return {value: value, criteria: iterator(value, index)};=0A=
    }).sort(function(left, right) {=0A=
      var a =3D left.criteria, b =3D right.criteria;=0A=
      return a < b ? -1 : a > b ? 1 : 0;=0A=
    }).pluck('value');=0A=
  },=0A=
=0A=
  toArray: function() {=0A=
    return this.map();=0A=
  },=0A=
=0A=
  zip: function() {=0A=
    var iterator =3D Prototype.K, args =3D $A(arguments);=0A=
    if (typeof args.last() =3D=3D 'function')=0A=
      iterator =3D args.pop();=0A=
=0A=
    var collections =3D [this].concat(args).map($A);=0A=
    return this.map(function(value, index) {=0A=
      return iterator(collections.pluck(index));=0A=
    });=0A=
  },=0A=
=0A=
  size: function() {=0A=
    return this.toArray().length;=0A=
  },=0A=
=0A=
  inspect: function() {=0A=
    return '#<Enumerable:' + this.toArray().inspect() + '>';=0A=
  }=0A=
}=0A=
=0A=
Object.extend(Enumerable, {=0A=
  map:     Enumerable.collect,=0A=
  find:    Enumerable.detect,=0A=
  select:  Enumerable.findAll,=0A=
  member:  Enumerable.include,=0A=
  entries: Enumerable.toArray=0A=
});=0A=
var $A =3D Array.from =3D function(iterable) {=0A=
  if (!iterable) return [];=0A=
  if (iterable.toArray) {=0A=
    return iterable.toArray();=0A=
  } else {=0A=
    var results =3D [];=0A=
    for (var i =3D 0, length =3D iterable.length; i < length; i++)=0A=
      results.push(iterable[i]);=0A=
    return results;=0A=
  }=0A=
}=0A=
=0A=
Object.extend(Array.prototype, Enumerable);=0A=
=0A=
if (!Array.prototype._reverse)=0A=
  Array.prototype._reverse =3D Array.prototype.reverse;=0A=
=0A=
Object.extend(Array.prototype, {=0A=
  _each: function(iterator) {=0A=
    for (var i =3D 0, length =3D this.length; i < length; i++)=0A=
      iterator(this[i]);=0A=
  },=0A=
=0A=
  clear: function() {=0A=
    this.length =3D 0;=0A=
    return this;=0A=
  },=0A=
=0A=
  first: function() {=0A=
    return this[0];=0A=
  },=0A=
=0A=
  last: function() {=0A=
    return this[this.length - 1];=0A=
  },=0A=
=0A=
  compact: function() {=0A=
    return this.select(function(value) {=0A=
      return value !=3D null;=0A=
    });=0A=
  },=0A=
=0A=
  flatten: function() {=0A=
    return this.inject([], function(array, value) {=0A=
      return array.concat(value && value.constructor =3D=3D Array ?=0A=
        value.flatten() : [value]);=0A=
    });=0A=
  },=0A=
=0A=
  without: function() {=0A=
    var values =3D $A(arguments);=0A=
    return this.select(function(value) {=0A=
      return !values.include(value);=0A=
    });=0A=
  },=0A=
=0A=
  indexOf: function(object) {=0A=
    for (var i =3D 0, length =3D this.length; i < length; i++)=0A=
      if (this[i] =3D=3D object) return i;=0A=
    return -1;=0A=
  },=0A=
=0A=
  reverse: function(inline) {=0A=
    return (inline !=3D=3D false ? this : this.toArray())._reverse();=0A=
  },=0A=
=0A=
  reduce: function() {=0A=
    return this.length > 1 ? this : this[0];=0A=
  },=0A=
=0A=
  uniq: function() {=0A=
    return this.inject([], function(array, value) {=0A=
      return array.include(value) ? array : array.concat([value]);=0A=
    });=0A=
  },=0A=
=0A=
  clone: function() {=0A=
    return [].concat(this);=0A=
  },=0A=
=0A=
  size: function() {=0A=
    return this.length;=0A=
  },=0A=
=0A=
  inspect: function() {=0A=
    return '[' + this.map(Object.inspect).join(', ') + ']';=0A=
  }=0A=
});=0A=
=0A=
Array.prototype.toArray =3D Array.prototype.clone;=0A=
=0A=
function $w(string){=0A=
  string =3D string.strip();=0A=
  return string ? string.split(/\s+/) : [];=0A=
}=0A=
=0A=
if(window.opera){=0A=
  Array.prototype.concat =3D function(){=0A=
    var array =3D [];=0A=
    for(var i =3D 0, length =3D this.length; i < length; i++) =
array.push(this[i]);=0A=
    for(var i =3D 0, length =3D arguments.length; i < length; i++) {=0A=
      if(arguments[i].constructor =3D=3D Array) {=0A=
        for(var j =3D 0, arrayLength =3D arguments[i].length; j < =
arrayLength; j++)=0A=
          array.push(arguments[i][j]);=0A=
      } else {=0A=
        array.push(arguments[i]);=0A=
      }=0A=
    }=0A=
    return array;=0A=
  }=0A=
}=0A=
var Hash =3D function(obj) {=0A=
  Object.extend(this, obj || {});=0A=
};=0A=
=0A=
Object.extend(Hash, {=0A=
  toQueryString: function(obj) {=0A=
    var parts =3D [];=0A=
=0A=
	  this.prototype._each.call(obj, function(pair) {=0A=
      if (!pair.key) return;=0A=
=0A=
      if (pair.value && pair.value.constructor =3D=3D Array) {=0A=
        var values =3D pair.value.compact();=0A=
        if (values.length < 2) pair.value =3D values.reduce();=0A=
        else {=0A=
        	key =3D encodeURIComponent(pair.key);=0A=
          values.each(function(value) {=0A=
            value =3D value !=3D undefined ? encodeURIComponent(value) : =
'';=0A=
            parts.push(key + '=3D' + encodeURIComponent(value));=0A=
          });=0A=
          return;=0A=
        }=0A=
      }=0A=
      if (pair.value =3D=3D undefined) pair[1] =3D '';=0A=
      parts.push(pair.map(encodeURIComponent).join('=3D'));=0A=
	  });=0A=
=0A=
    return parts.join('&');=0A=
  }=0A=
});=0A=
=0A=
Object.extend(Hash.prototype, Enumerable);=0A=
Object.extend(Hash.prototype, {=0A=
  _each: function(iterator) {=0A=
    for (var key in this) {=0A=
      var value =3D this[key];=0A=
      if (value && value =3D=3D Hash.prototype[key]) continue;=0A=
=0A=
      var pair =3D [key, value];=0A=
      pair.key =3D key;=0A=
      pair.value =3D value;=0A=
      iterator(pair);=0A=
    }=0A=
  },=0A=
=0A=
  keys: function() {=0A=
    return this.pluck('key');=0A=
  },=0A=
=0A=
  values: function() {=0A=
    return this.pluck('value');=0A=
  },=0A=
=0A=
  merge: function(hash) {=0A=
    return $H(hash).inject(this, function(mergedHash, pair) {=0A=
      mergedHash[pair.key] =3D pair.value;=0A=
      return mergedHash;=0A=
    });=0A=
  },=0A=
=0A=
  remove: function() {=0A=
    var result;=0A=
    for(var i =3D 0, length =3D arguments.length; i < length; i++) {=0A=
      var value =3D this[arguments[i]];=0A=
      if (value !=3D=3D undefined){=0A=
        if (result =3D=3D=3D undefined) result =3D value;=0A=
        else {=0A=
          if (result.constructor !=3D Array) result =3D [result];=0A=
          result.push(value)=0A=
        }=0A=
      }=0A=
      delete this[arguments[i]];=0A=
    }=0A=
    return result;=0A=
  },=0A=
=0A=
  toQueryString: function() {=0A=
    return Hash.toQueryString(this);=0A=
  },=0A=
=0A=
  inspect: function() {=0A=
    return '#<Hash:{' + this.map(function(pair) {=0A=
      return pair.map(Object.inspect).join(': ');=0A=
    }).join(', ') + '}>';=0A=
  }=0A=
});=0A=
=0A=
function $H(object) {=0A=
  if (object && object.constructor =3D=3D Hash) return object;=0A=
  return new Hash(object);=0A=
};=0A=
ObjectRange =3D Class.create();=0A=
Object.extend(ObjectRange.prototype, Enumerable);=0A=
Object.extend(ObjectRange.prototype, {=0A=
  initialize: function(start, end, exclusive) {=0A=
    this.start =3D start;=0A=
    this.end =3D end;=0A=
    this.exclusive =3D exclusive;=0A=
  },=0A=
=0A=
  _each: function(iterator) {=0A=
    var value =3D this.start;=0A=
    while (this.include(value)) {=0A=
      iterator(value);=0A=
      value =3D value.succ();=0A=
    }=0A=
  },=0A=
=0A=
  include: function(value) {=0A=
    if (value < this.start)=0A=
      return false;=0A=
    if (this.exclusive)=0A=
      return value < this.end;=0A=
    return value <=3D this.end;=0A=
  }=0A=
});=0A=
=0A=
var $R =3D function(start, end, exclusive) {=0A=
  return new ObjectRange(start, end, exclusive);=0A=
}=0A=
=0A=
var Ajax =3D {=0A=
  getTransport: function() {=0A=
    return Try.these(=0A=
      function() {return new XMLHttpRequest()},=0A=
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},=0A=
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}=0A=
    ) || false;=0A=
  },=0A=
=0A=
  activeRequestCount: 0=0A=
}=0A=
=0A=
Ajax.Responders =3D {=0A=
  responders: [],=0A=
=0A=
  _each: function(iterator) {=0A=
    this.responders._each(iterator);=0A=
  },=0A=
=0A=
  register: function(responder) {=0A=
    if (!this.include(responder))=0A=
      this.responders.push(responder);=0A=
  },=0A=
=0A=
  unregister: function(responder) {=0A=
    this.responders =3D this.responders.without(responder);=0A=
  },=0A=
=0A=
  dispatch: function(callback, request, transport, json) {=0A=
    this.each(function(responder) {=0A=
      if (typeof responder[callback] =3D=3D 'function') {=0A=
        try {=0A=
          responder[callback].apply(responder, [request, transport, =
json]);=0A=
        } catch (e) {}=0A=
      }=0A=
    });=0A=
  }=0A=
};=0A=
=0A=
Object.extend(Ajax.Responders, Enumerable);=0A=
=0A=
Ajax.Responders.register({=0A=
  onCreate: function() {=0A=
    Ajax.activeRequestCount++;=0A=
  },=0A=
  onComplete: function() {=0A=
    Ajax.activeRequestCount--;=0A=
  }=0A=
});=0A=
=0A=
Ajax.Base =3D function() {};=0A=
Ajax.Base.prototype =3D {=0A=
  setOptions: function(options) {=0A=
    this.options =3D {=0A=
      method:       'post',=0A=
      asynchronous: true,=0A=
      contentType:  'application/x-www-form-urlencoded',=0A=
      encoding:     'UTF-8',=0A=
      parameters:   ''=0A=
    }=0A=
    Object.extend(this.options, options || {});=0A=
=0A=
    this.options.method =3D this.options.method.toLowerCase();=0A=
    if (typeof this.options.parameters =3D=3D 'string')=0A=
      this.options.parameters =3D =
this.options.parameters.toQueryParams();=0A=
  }=0A=
}=0A=
=0A=
Ajax.Request =3D Class.create();=0A=
Ajax.Request.Events =3D=0A=
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];=0A=
=0A=
Ajax.Request.prototype =3D Object.extend(new Ajax.Base(), {=0A=
  _complete: false,=0A=
=0A=
  initialize: function(url, options) {=0A=
    this.transport =3D Ajax.getTransport();=0A=
    this.setOptions(options);=0A=
    this.request(url);=0A=
  },=0A=
=0A=
  request: function(url) {=0A=
    this.url =3D url;=0A=
    this.method =3D this.options.method;=0A=
    var params =3D this.options.parameters;=0A=
=0A=
    if (!['get', 'post'].include(this.method)) {=0A=
      // simulate other verbs over post=0A=
      params['_method'] =3D this.method;=0A=
      this.method =3D 'post';=0A=
    }=0A=
=0A=
    params =3D Hash.toQueryString(params);=0A=
    if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) =
params +=3D '&_=3D'=0A=
=0A=
    // when GET, append parameters to URL=0A=
    if (this.method =3D=3D 'get' && params)=0A=
      this.url +=3D (this.url.indexOf('?') > -1 ? '&' : '?') + params;=0A=
=0A=
    try {=0A=
      Ajax.Responders.dispatch('onCreate', this, this.transport);=0A=
=0A=
      this.transport.open(this.method.toUpperCase(), this.url,=0A=
        this.options.asynchronous);=0A=
=0A=
      if (this.options.asynchronous)=0A=
        setTimeout(function() { this.respondToReadyState(1) =
}.bind(this), 10);=0A=
=0A=
      this.transport.onreadystatechange =3D =
this.onStateChange.bind(this);=0A=
      this.setRequestHeaders();=0A=
=0A=
      var body =3D this.method =3D=3D 'post' ? (this.options.postBody || =
params) : null;=0A=
=0A=
      this.transport.send(body);=0A=
=0A=
      /* Force Firefox to handle ready state 4 for synchronous requests =
*/=0A=
      if (!this.options.asynchronous && this.transport.overrideMimeType)=0A=
        this.onStateChange();=0A=
=0A=
    }=0A=
    catch (e) {=0A=
      this.dispatchException(e);=0A=
    }=0A=
  },=0A=
=0A=
  onStateChange: function() {=0A=
    var readyState =3D this.transport.readyState;=0A=
    if (readyState > 1 && !((readyState =3D=3D 4) && this._complete))=0A=
      this.respondToReadyState(this.transport.readyState);=0A=
  },=0A=
=0A=
  setRequestHeaders: function() {=0A=
    var headers =3D {=0A=
      'X-Requested-With': 'XMLHttpRequest',=0A=
      'X-Prototype-Version': Prototype.Version,=0A=
      'Accept': 'text/javascript, text/html, application/xml, text/xml, =
*/*'=0A=
    };=0A=
=0A=
    if (this.method =3D=3D 'post') {=0A=
      headers['Content-type'] =3D this.options.contentType +=0A=
        (this.options.encoding ? '; charset=3D' + this.options.encoding =
: '');=0A=
=0A=
      /* Force "Connection: close" for older Mozilla browsers to work=0A=
       * around a bug where XMLHttpRequest sends an incorrect=0A=
       * Content-length header. See Mozilla Bugzilla #246651.=0A=
       */=0A=
      if (this.transport.overrideMimeType &&=0A=
          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < =
2005)=0A=
            headers['Connection'] =3D 'close';=0A=
    }=0A=
=0A=
    // user-defined headers=0A=
    if (typeof this.options.requestHeaders =3D=3D 'object') {=0A=
      var extras =3D this.options.requestHeaders;=0A=
=0A=
      if (typeof extras.push =3D=3D 'function')=0A=
        for (var i =3D 0, length =3D extras.length; i < length; i +=3D 2)=0A=
          headers[extras[i]] =3D extras[i+1];=0A=
      else=0A=
        $H(extras).each(function(pair) { headers[pair.key] =3D =
pair.value });=0A=
    }=0A=
=0A=
    for (var name in headers)=0A=
      this.transport.setRequestHeader(name, headers[name]);=0A=
  },=0A=
=0A=
  success: function() {=0A=
    return !this.transport.status=0A=
        || (this.transport.status >=3D 200 && this.transport.status < =
300);=0A=
  },=0A=
=0A=
  respondToReadyState: function(readyState) {=0A=
    var state =3D Ajax.Request.Events[readyState];=0A=
    var transport =3D this.transport, json =3D this.evalJSON();=0A=
=0A=
    if (state =3D=3D 'Complete') {=0A=
      try {=0A=
        this._complete =3D true;=0A=
        (this.options['on' + this.transport.status]=0A=
         || this.options['on' + (this.success() ? 'Success' : 'Failure')]=0A=
         || Prototype.emptyFunction)(transport, json);=0A=
      } catch (e) {=0A=
        this.dispatchException(e);=0A=
      }=0A=
=0A=
      if ((this.getHeader('Content-type') || 'text/javascript').strip().=0A=
        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))=0A=
          this.evalResponse();=0A=
    }=0A=
=0A=
    try {=0A=
      (this.options['on' + state] || Prototype.emptyFunction)(transport, =
json);=0A=
      Ajax.Responders.dispatch('on' + state, this, transport, json);=0A=
    } catch (e) {=0A=
      this.dispatchException(e);=0A=
    }=0A=
=0A=
    if (state =3D=3D 'Complete') {=0A=
      // avoid memory leak in MSIE: clean up=0A=
      this.transport.onreadystatechange =3D Prototype.emptyFunction;=0A=
    }=0A=
  },=0A=
=0A=
  getHeader: function(name) {=0A=
    try {=0A=
      return this.transport.getResponseHeader(name);=0A=
    } catch (e) { return null }=0A=
  },=0A=
=0A=
  evalJSON: function() {=0A=
    try {=0A=
      var json =3D this.getHeader('X-JSON');=0A=
      return json ? eval('(' + json + ')') : null;=0A=
    } catch (e) { return null }=0A=
  },=0A=
=0A=
  evalResponse: function() {=0A=
    try {=0A=
      return eval(this.transport.responseText);=0A=
    } catch (e) {=0A=
      this.dispatchException(e);=0A=
    }=0A=
  },=0A=
=0A=
  dispatchException: function(exception) {=0A=
    (this.options.onException || Prototype.emptyFunction)(this, =
exception);=0A=
    Ajax.Responders.dispatch('onException', this, exception);=0A=
  }=0A=
});=0A=
=0A=
Ajax.Updater =3D Class.create();=0A=
=0A=
Object.extend(Object.extend(Ajax.Updater.prototype, =
Ajax.Request.prototype), {=0A=
  initialize: function(container, url, options) {=0A=
    this.container =3D {=0A=
      success: (container.success || container),=0A=
      failure: (container.failure || (container.success ? null : =
container))=0A=
    }=0A=
=0A=
    this.transport =3D Ajax.getTransport();=0A=
    this.setOptions(options);=0A=
=0A=
    var onComplete =3D this.options.onComplete || =
Prototype.emptyFunction;=0A=
    this.options.onComplete =3D (function(transport, param) {=0A=
      this.updateContent();=0A=
      onComplete(transport, param);=0A=
    }).bind(this);=0A=
=0A=
    this.request(url);=0A=
  },=0A=
=0A=
  updateContent: function() {=0A=
    var receiver =3D this.container[this.success() ? 'success' : =
'failure'];=0A=
    var response =3D this.transport.responseText;=0A=
=0A=
    if (!this.options.evalScripts) response =3D response.stripScripts();=0A=
=0A=
    if (receiver =3D $(receiver)) {=0A=
      if (this.options.insertion)=0A=
        new this.options.insertion(receiver, response);=0A=
      else=0A=
        receiver.update(response);=0A=
    }=0A=
=0A=
    if (this.success()) {=0A=
      if (this.onComplete)=0A=
        setTimeout(this.onComplete.bind(this), 10);=0A=
    }=0A=
  }=0A=
});=0A=
=0A=
Ajax.PeriodicalUpdater =3D Class.create();=0A=
Ajax.PeriodicalUpdater.prototype =3D Object.extend(new Ajax.Base(), {=0A=
  initialize: function(container, url, options) {=0A=
    this.setOptions(options);=0A=
    this.onComplete =3D this.options.onComplete;=0A=
=0A=
    this.frequency =3D (this.options.frequency || 2);=0A=
    this.decay =3D (this.options.decay || 1);=0A=
=0A=
    this.updater =3D {};=0A=
    this.container =3D container;=0A=
    this.url =3D url;=0A=
=0A=
    this.start();=0A=
  },=0A=
=0A=
  start: function() {=0A=
    this.options.onComplete =3D this.updateComplete.bind(this);=0A=
    this.onTimerEvent();=0A=
  },=0A=
=0A=
  stop: function() {=0A=
    this.updater.options.onComplete =3D undefined;=0A=
    clearTimeout(this.timer);=0A=
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);=0A=
  },=0A=
=0A=
  updateComplete: function(request) {=0A=
    if (this.options.decay) {=0A=
      this.decay =3D (request.responseText =3D=3D this.lastText ?=0A=
        this.decay * this.options.decay : 1);=0A=
=0A=
      this.lastText =3D request.responseText;=0A=
    }=0A=
    this.timer =3D setTimeout(this.onTimerEvent.bind(this),=0A=
      this.decay * this.frequency * 1000);=0A=
  },=0A=
=0A=
  onTimerEvent: function() {=0A=
    this.updater =3D new Ajax.Updater(this.container, this.url, =
this.options);=0A=
  }=0A=
});=0A=
function $(element) {=0A=
  if (arguments.length > 1) {=0A=
    for (var i =3D 0, elements =3D [], length =3D arguments.length; i < =
length; i++)=0A=
      elements.push($(arguments[i]));=0A=
    return elements;=0A=
  }=0A=
  if (typeof element =3D=3D 'string')=0A=
    element =3D document.getElementById(element);=0A=
  return Element.extend(element);=0A=
}=0A=
=0A=
if (Prototype.BrowserFeatures.XPath) {=0A=
  document._getElementsByXPath =3D function(expression, parentElement) {=0A=
    var results =3D [];=0A=
    var query =3D document.evaluate(expression, $(parentElement) || =
document,=0A=
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);=0A=
    for (var i =3D 0, length =3D query.snapshotLength; i < length; i++)=0A=
      results.push(query.snapshotItem(i));=0A=
    return results;=0A=
  };=0A=
}=0A=
=0A=
document.getElementsByClassName =3D function(className, parentElement) {=0A=
  if (Prototype.BrowserFeatures.XPath) {=0A=
    var q =3D ".//*[contains(concat(' ', @class, ' '), ' " + className + =
" ')]";=0A=
    return document._getElementsByXPath(q, parentElement);=0A=
  } else {=0A=
    var children =3D ($(parentElement) || =
document.body).getElementsByTagName('*');=0A=
    var elements =3D [], child;=0A=
    for (var i =3D 0, length =3D children.length; i < length; i++) {=0A=
      child =3D children[i];=0A=
      if (Element.hasClassName(child, className))=0A=
        elements.push(Element.extend(child));=0A=
    }=0A=
    return elements;=0A=
  }=0A=
};=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
if (!window.Element)=0A=
  var Element =3D new Object();=0A=
=0A=
Element.extend =3D function(element) {=0A=
  if (!element || _nativeExtensions || element.nodeType =3D=3D 3) return =
element;=0A=
=0A=
  if (!element._extended && element.tagName && element !=3D window) {=0A=
    var methods =3D Object.clone(Element.Methods), cache =3D =
Element.extend.cache;=0A=
=0A=
    if (element.tagName =3D=3D 'FORM')=0A=
      Object.extend(methods, Form.Methods);=0A=
    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))=0A=
      Object.extend(methods, Form.Element.Methods);=0A=
=0A=
    Object.extend(methods, Element.Methods.Simulated);=0A=
=0A=
    for (var property in methods) {=0A=
      var value =3D methods[property];=0A=
      if (typeof value =3D=3D 'function' && !(property in element))=0A=
        element[property] =3D cache.findOrStore(value);=0A=
    }=0A=
  }=0A=
=0A=
  element._extended =3D true;=0A=
  return element;=0A=
};=0A=
=0A=
Element.extend.cache =3D {=0A=
  findOrStore: function(value) {=0A=
    return this[value] =3D this[value] || function() {=0A=
      return value.apply(null, [this].concat($A(arguments)));=0A=
    }=0A=
  }=0A=
};=0A=
=0A=
Element.Methods =3D {=0A=
  visible: function(element) {=0A=
    return $(element).style.display !=3D 'none';=0A=
  },=0A=
=0A=
  toggle: function(element) {=0A=
    element =3D $(element);=0A=
    Element[Element.visible(element) ? 'hide' : 'show'](element);=0A=
    return element;=0A=
  },=0A=
=0A=
  hide: function(element) {=0A=
    $(element).style.display =3D 'none';=0A=
    return element;=0A=
  },=0A=
=0A=
  show: function(element) {=0A=
    $(element).style.display =3D '';=0A=
    return element;=0A=
  },=0A=
=0A=
  remove: function(element) {=0A=
    element =3D $(element);=0A=
    element.parentNode.removeChild(element);=0A=
    return element;=0A=
  },=0A=
=0A=
  update: function(element, html) {=0A=
    html =3D typeof html =3D=3D 'undefined' ? '' : html.toString();=0A=
    $(element).innerHTML =3D html.stripScripts();=0A=
    setTimeout(function() {html.evalScripts()}, 10);=0A=
    return element;=0A=
  },=0A=
=0A=
  replace: function(element, html) {=0A=
    element =3D $(element);=0A=
    html =3D typeof html =3D=3D 'undefined' ? '' : html.toString();=0A=
    if (element.outerHTML) {=0A=
      element.outerHTML =3D html.stripScripts();=0A=
    } else {=0A=
      var range =3D element.ownerDocument.createRange();=0A=
      range.selectNodeContents(element);=0A=
      element.parentNode.replaceChild(=0A=
        range.createContextualFragment(html.stripScripts()), element);=0A=
    }=0A=
    setTimeout(function() {html.evalScripts()}, 10);=0A=
    return element;=0A=
  },=0A=
=0A=
  inspect: function(element) {=0A=
    element =3D $(element);=0A=
    var result =3D '<' + element.tagName.toLowerCase();=0A=
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {=0A=
      var property =3D pair.first(), attribute =3D pair.last();=0A=
      var value =3D (element[property] || '').toString();=0A=
      if (value) result +=3D ' ' + attribute + '=3D' + =
value.inspect(true);=0A=
    });=0A=
    return result + '>';=0A=
  },=0A=
=0A=
  recursivelyCollect: function(element, property) {=0A=
    element =3D $(element);=0A=
    var elements =3D [];=0A=
    while (element =3D element[property])=0A=
      if (element.nodeType =3D=3D 1)=0A=
        elements.push(Element.extend(element));=0A=
    return elements;=0A=
  },=0A=
=0A=
  ancestors: function(element) {=0A=
    return $(element).recursivelyCollect('parentNode');=0A=
  },=0A=
=0A=
  descendants: function(element) {=0A=
    return $A($(element).getElementsByTagName('*'));=0A=
  },=0A=
=0A=
  immediateDescendants: function(element) {=0A=
    if (!(element =3D $(element).firstChild)) return [];=0A=
    while (element && element.nodeType !=3D 1) element =3D =
element.nextSibling;=0A=
    if (element) return [element].concat($(element).nextSiblings());=0A=
    return [];=0A=
  },=0A=
=0A=
  previousSiblings: function(element) {=0A=
    return $(element).recursivelyCollect('previousSibling');=0A=
  },=0A=
=0A=
  nextSiblings: function(element) {=0A=
    return $(element).recursivelyCollect('nextSibling');=0A=
  },=0A=
=0A=
  siblings: function(element) {=0A=
    element =3D $(element);=0A=
    return =
element.previousSiblings().reverse().concat(element.nextSiblings());=0A=
  },=0A=
=0A=
  match: function(element, selector) {=0A=
    if (typeof selector =3D=3D 'string')=0A=
      selector =3D new Selector(selector);=0A=
    return selector.match($(element));=0A=
  },=0A=
=0A=
  up: function(element, expression, index) {=0A=
    return Selector.findElement($(element).ancestors(), expression, =
index);=0A=
  },=0A=
=0A=
  down: function(element, expression, index) {=0A=
    return Selector.findElement($(element).descendants(), expression, =
index);=0A=
  },=0A=
=0A=
  previous: function(element, expression, index) {=0A=
    return Selector.findElement($(element).previousSiblings(), =
expression, index);=0A=
  },=0A=
=0A=
  next: function(element, expression, index) {=0A=
    return Selector.findElement($(element).nextSiblings(), expression, =
index);=0A=
  },=0A=
=0A=
  getElementsBySelector: function() {=0A=
    var args =3D $A(arguments), element =3D $(args.shift());=0A=
    return Selector.findChildElements(element, args);=0A=
  },=0A=
=0A=
  getElementsByClassName: function(element, className) {=0A=
    return document.getElementsByClassName(className, element);=0A=
  },=0A=
=0A=
  readAttribute: function(element, name) {=0A=
    element =3D $(element);=0A=
    if (document.all && !window.opera) {=0A=
      var t =3D Element._attributeTranslations;=0A=
      if (t.values[name]) return t.values[name](element, name);=0A=
      if (t.names[name])  name =3D t.names[name];=0A=
      var attribute =3D element.attributes[name];=0A=
      if(attribute) return attribute.nodeValue;=0A=
    }=0A=
    return element.getAttribute(name);=0A=
  },=0A=
=0A=
  getHeight: function(element) {=0A=
    return $(element).getDimensions().height;=0A=
  },=0A=
=0A=
  getWidth: function(element) {=0A=
    return $(element).getDimensions().width;=0A=
  },=0A=
=0A=
  classNames: function(element) {=0A=
    return new Element.ClassNames(element);=0A=
  },=0A=
=0A=
  hasClassName: function(element, className) {=0A=
    if (!(element =3D $(element))) return;=0A=
    var elementClassName =3D element.className;=0A=
    if (elementClassName.length =3D=3D 0) return false;=0A=
    if (elementClassName =3D=3D className ||=0A=
        elementClassName.match(new RegExp("(^|\\s)" + className + =
"(\\s|$)")))=0A=
      return true;=0A=
    return false;=0A=
  },=0A=
=0A=
  addClassName: function(element, className) {=0A=
    if (!(element =3D $(element))) return;=0A=
    Element.classNames(element).add(className);=0A=
    return element;=0A=
  },=0A=
=0A=
  removeClassName: function(element, className) {=0A=
    if (!(element =3D $(element))) return;=0A=
    Element.classNames(element).remove(className);=0A=
    return element;=0A=
  },=0A=
=0A=
  toggleClassName: function(element, className) {=0A=
    if (!(element =3D $(element))) return;=0A=
    Element.classNames(element)[element.hasClassName(className) ? =
'remove' : 'add'](className);=0A=
    return element;=0A=
  },=0A=
=0A=
  observe: function() {=0A=
    Event.observe.apply(Event, arguments);=0A=
    return $A(arguments).first();=0A=
  },=0A=
=0A=
  stopObserving: function() {=0A=
    Event.stopObserving.apply(Event, arguments);=0A=
    return $A(arguments).first();=0A=
  },=0A=
=0A=
  // removes whitespace-only text node children=0A=
  cleanWhitespace: function(element) {=0A=
    element =3D $(element);=0A=
    var node =3D element.firstChild;=0A=
    while (node) {=0A=
      var nextNode =3D node.nextSibling;=0A=
      if (node.nodeType =3D=3D 3 && !/\S/.test(node.nodeValue))=0A=
        element.removeChild(node);=0A=
      node =3D nextNode;=0A=
    }=0A=
    return element;=0A=
  },=0A=
=0A=
  empty: function(element) {=0A=
    return $(element).innerHTML.match(/^\s*$/);=0A=
  },=0A=
=0A=
  descendantOf: function(element, ancestor) {=0A=
    element =3D $(element), ancestor =3D $(ancestor);=0A=
    while (element =3D element.parentNode)=0A=
      if (element =3D=3D ancestor) return true;=0A=
    return false;=0A=
  },=0A=
=0A=
  scrollTo: function(element) {=0A=
    element =3D $(element);=0A=
    var pos =3D Position.cumulativeOffset(element);=0A=
    window.scrollTo(pos[0], pos[1]);=0A=
    return element;=0A=
  },=0A=
=0A=
  getStyle: function(element, style) {=0A=
    element =3D $(element);=0A=
    if (['float','cssFloat'].include(style))=0A=
      style =3D (typeof element.style.styleFloat !=3D 'undefined' ? =
'styleFloat' : 'cssFloat');=0A=
    style =3D style.camelize();=0A=
    var value =3D element.style[style];=0A=
    if (!value) {=0A=
      if (document.defaultView && document.defaultView.getComputedStyle) =
{=0A=
        var css =3D document.defaultView.getComputedStyle(element, null);=0A=
        value =3D css ? css[style] : null;=0A=
      } else if (element.currentStyle) {=0A=
        value =3D element.currentStyle[style];=0A=
      }=0A=
    }=0A=
=0A=
    if((value =3D=3D 'auto') && ['width','height'].include(style) && =
(element.getStyle('display') !=3D 'none'))=0A=
      value =3D element['offset'+style.capitalize()] + 'px';=0A=
=0A=
    if (window.opera && ['left', 'top', 'right', =
'bottom'].include(style))=0A=
      if (Element.getStyle(element, 'position') =3D=3D 'static') value =
=3D 'auto';=0A=
    if(style =3D=3D 'opacity') {=0A=
      if(value) return parseFloat(value);=0A=
      if(value =3D (element.getStyle('filter') || =
'').match(/alpha\(opacity=3D(.*)\)/))=0A=
        if(value[1]) return parseFloat(value[1]) / 100;=0A=
      return 1.0;=0A=
    }=0A=
    return value =3D=3D 'auto' ? null : value;=0A=
  },=0A=
=0A=
  setStyle: function(element, style) {=0A=
    element =3D $(element);=0A=
    for (var name in style) {=0A=
      var value =3D style[name];=0A=
      if(name =3D=3D 'opacity') {=0A=
        if (value =3D=3D 1) {=0A=
          value =3D (/Gecko/.test(navigator.userAgent) &&=0A=
            !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? =
0.999999 : 1.0;=0A=
          if(/MSIE/.test(navigator.userAgent) && !window.opera)=0A=
            element.style.filter =3D =
element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');=0A=
        } else if(value =3D=3D '') {=0A=
          if(/MSIE/.test(navigator.userAgent) && !window.opera)=0A=
            element.style.filter =3D =
element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');=0A=
        } else {=0A=
          if(value < 0.00001) value =3D 0;=0A=
          if(/MSIE/.test(navigator.userAgent) && !window.opera)=0A=
            element.style.filter =3D =
element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +=0A=
              'alpha(opacity=3D'+value*100+')';=0A=
        }=0A=
      } else if(['float','cssFloat'].include(name)) name =3D (typeof =
element.style.styleFloat !=3D 'undefined') ? 'styleFloat' : 'cssFloat';=0A=
      element.style[name.camelize()] =3D value;=0A=
    }=0A=
    return element;=0A=
  },=0A=
=0A=
  getDimensions: function(element) {=0A=
    element =3D $(element);=0A=
    var display =3D $(element).getStyle('display');=0A=
    if (display !=3D 'none' && display !=3D null) // Safari bug=0A=
      return {width: element.offsetWidth, height: element.offsetHeight};=0A=
=0A=
    // All *Width and *Height properties give 0 on elements with display =
none,=0A=
    // so enable the element temporarily=0A=
    var els =3D element.style;=0A=
    var originalVisibility =3D els.visibility;=0A=
    var originalPosition =3D els.position;=0A=
    var originalDisplay =3D els.display;=0A=
    els.visibility =3D 'hidden';=0A=
    els.position =3D 'absolute';=0A=
    els.display =3D 'block';=0A=
    var originalWidth =3D element.clientWidth;=0A=
    var originalHeight =3D element.clientHeight;=0A=
    els.display =3D originalDisplay;=0A=
    els.position =3D originalPosition;=0A=
    els.visibility =3D originalVisibility;=0A=
    return {width: originalWidth, height: originalHeight};=0A=
  },=0A=
=0A=
  makePositioned: function(element) {=0A=
    element =3D $(element);=0A=
    var pos =3D Element.getStyle(element, 'position');=0A=
    if (pos =3D=3D 'static' || !pos) {=0A=
      element._madePositioned =3D true;=0A=
      element.style.position =3D 'relative';=0A=
      // Opera returns the offset relative to the positioning context, =
when an=0A=
      // element is position relative but top and left have not been =
defined=0A=
      if (window.opera) {=0A=
        element.style.top =3D 0;=0A=
        element.style.left =3D 0;=0A=
      }=0A=
    }=0A=
    return element;=0A=
  },=0A=
=0A=
  undoPositioned: function(element) {=0A=
    element =3D $(element);=0A=
    if (element._madePositioned) {=0A=
      element._madePositioned =3D undefined;=0A=
      element.style.position =3D=0A=
        element.style.top =3D=0A=
        element.style.left =3D=0A=
        element.style.bottom =3D=0A=
        element.style.right =3D '';=0A=
    }=0A=
    return element;=0A=
  },=0A=
=0A=
  makeClipping: function(element) {=0A=
    element =3D $(element);=0A=
    if (element._overflow) return element;=0A=
    element._overflow =3D element.style.overflow || 'auto';=0A=
    if ((Element.getStyle(element, 'overflow') || 'visible') !=3D =
'hidden')=0A=
      element.style.overflow =3D 'hidden';=0A=
    return element;=0A=
  },=0A=
=0A=
  undoClipping: function(element) {=0A=
    element =3D $(element);=0A=
    if (!element._overflow) return element;=0A=
    element.style.overflow =3D element._overflow =3D=3D 'auto' ? '' : =
element._overflow;=0A=
    element._overflow =3D null;=0A=
    return element;=0A=
  }=0A=
};=0A=
=0A=
Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});=0A=
=0A=
Element._attributeTranslations =3D {};=0A=
=0A=
Element._attributeTranslations.names =3D {=0A=
  colspan:   "colSpan",=0A=
  rowspan:   "rowSpan",=0A=
  valign:    "vAlign",=0A=
  datetime:  "dateTime",=0A=
  accesskey: "accessKey",=0A=
  tabindex:  "tabIndex",=0A=
  enctype:   "encType",=0A=
  maxlength: "maxLength",=0A=
  readonly:  "readOnly",=0A=
  longdesc:  "longDesc"=0A=
};=0A=
=0A=
Element._attributeTranslations.values =3D {=0A=
  _getAttr: function(element, attribute) {=0A=
    return element.getAttribute(attribute, 2);=0A=
  },=0A=
=0A=
  _flag: function(element, attribute) {=0A=
    return $(element).hasAttribute(attribute) ? attribute : null;=0A=
  },=0A=
=0A=
  style: function(element) {=0A=
    return element.style.cssText.toLowerCase();=0A=
  },=0A=
=0A=
  title: function(element) {=0A=
    var node =3D element.getAttributeNode('title');=0A=
    return node.specified ? node.nodeValue : null;=0A=
  }=0A=
};=0A=
=0A=
Object.extend(Element._attributeTranslations.values, {=0A=
  href: Element._attributeTranslations.values._getAttr,=0A=
  src:  Element._attributeTranslations.values._getAttr,=0A=
  disabled: Element._attributeTranslations.values._flag,=0A=
  checked:  Element._attributeTranslations.values._flag,=0A=
  readonly: Element._attributeTranslations.values._flag,=0A=
  multiple: Element._attributeTranslations.values._flag=0A=
});=0A=
=0A=
Element.Methods.Simulated =3D {=0A=
  hasAttribute: function(element, attribute) {=0A=
    var t =3D Element._attributeTranslations;=0A=
    attribute =3D t.names[attribute] || attribute;=0A=
    return $(element).getAttributeNode(attribute).specified;=0A=
  }=0A=
};=0A=
=0A=
// IE is missing .innerHTML support for TABLE-related elements=0A=
if (document.all && !window.opera){=0A=
  Element.Methods.update =3D function(element, html) {=0A=
    element =3D $(element);=0A=
    html =3D typeof html =3D=3D 'undefined' ? '' : html.toString();=0A=
    var tagName =3D element.tagName.toUpperCase();=0A=
    if (['THEAD','TBODY','TR','TD'].include(tagName)) {=0A=
      var div =3D document.createElement('div');=0A=
      switch (tagName) {=0A=
        case 'THEAD':=0A=
        case 'TBODY':=0A=
          div.innerHTML =3D '<table><tbody>' +  html.stripScripts() + =
'</tbody></table>';=0A=
          depth =3D 2;=0A=
          break;=0A=
        case 'TR':=0A=
          div.innerHTML =3D '<table><tbody><tr>' +  html.stripScripts() =
+ '</tr></tbody></table>';=0A=
          depth =3D 3;=0A=
          break;=0A=
        case 'TD':=0A=
          div.innerHTML =3D '<table><tbody><tr><td>' +  =
html.stripScripts() + '</td></tr></tbody></table>';=0A=
          depth =3D 4;=0A=
      }=0A=
      $A(element.childNodes).each(function(node){=0A=
        element.removeChild(node)=0A=
      });=0A=
      depth.times(function(){ div =3D div.firstChild });=0A=
=0A=
      $A(div.childNodes).each(=0A=
        function(node){ element.appendChild(node) });=0A=
    } else {=0A=
      element.innerHTML =3D html.stripScripts();=0A=
    }=0A=
    setTimeout(function() {html.evalScripts()}, 10);=0A=
    return element;=0A=
  }=0A=
};=0A=
=0A=
Object.extend(Element, Element.Methods);=0A=
=0A=
var _nativeExtensions =3D false;=0A=
=0A=
if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))=0A=
  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {=0A=
    var className =3D 'HTML' + tag + 'Element';=0A=
    if(window[className]) return;=0A=
    var klass =3D window[className] =3D {};=0A=
    klass.prototype =3D document.createElement(tag ? tag.toLowerCase() : =
'div').__proto__;=0A=
  });=0A=
=0A=
Element.addMethods =3D function(methods) {=0A=
  Object.extend(Element.Methods, methods || {});=0A=
=0A=
  function copy(methods, destination, onlyIfAbsent) {=0A=
    onlyIfAbsent =3D onlyIfAbsent || false;=0A=
    var cache =3D Element.extend.cache;=0A=
    for (var property in methods) {=0A=
      var value =3D methods[property];=0A=
      if (!onlyIfAbsent || !(property in destination))=0A=
        destination[property] =3D cache.findOrStore(value);=0A=
    }=0A=
  }=0A=
=0A=
  if (typeof HTMLElement !=3D 'undefined') {=0A=
    copy(Element.Methods, HTMLElement.prototype);=0A=
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);=0A=
    copy(Form.Methods, HTMLFormElement.prototype);=0A=
    [HTMLInputElement, HTMLTextAreaElement, =
HTMLSelectElement].each(function(klass) {=0A=
      copy(Form.Element.Methods, klass.prototype);=0A=
    });=0A=
    _nativeExtensions =3D true;=0A=
  }=0A=
}=0A=
=0A=
var Toggle =3D new Object();=0A=
Toggle.display =3D Element.toggle;=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Abstract.Insertion =3D function(adjacency) {=0A=
  this.adjacency =3D adjacency;=0A=
}=0A=
=0A=
Abstract.Insertion.prototype =3D {=0A=
  initialize: function(element, content) {=0A=
    this.element =3D $(element);=0A=
    this.content =3D content.stripScripts();=0A=
=0A=
    if (this.adjacency && this.element.insertAdjacentHTML) {=0A=
      try {=0A=
        this.element.insertAdjacentHTML(this.adjacency, this.content);=0A=
      } catch (e) {=0A=
        var tagName =3D this.element.tagName.toUpperCase();=0A=
        if (['TBODY', 'TR'].include(tagName)) {=0A=
          this.insertContent(this.contentFromAnonymousTable());=0A=
        } else {=0A=
          throw e;=0A=
        }=0A=
      }=0A=
    } else {=0A=
      this.range =3D this.element.ownerDocument.createRange();=0A=
      if (this.initializeRange) this.initializeRange();=0A=
      =
this.insertContent([this.range.createContextualFragment(this.content)]);=0A=
    }=0A=
=0A=
    setTimeout(function() {content.evalScripts()}, 10);=0A=
  },=0A=
=0A=
  contentFromAnonymousTable: function() {=0A=
    var div =3D document.createElement('div');=0A=
    div.innerHTML =3D '<table><tbody>' + this.content + =
'</tbody></table>';=0A=
    return $A(div.childNodes[0].childNodes[0].childNodes);=0A=
  }=0A=
}=0A=
=0A=
var Insertion =3D new Object();=0A=
=0A=
Insertion.Before =3D Class.create();=0A=
Insertion.Before.prototype =3D Object.extend(new =
Abstract.Insertion('beforeBegin'), {=0A=
  initializeRange: function() {=0A=
    this.range.setStartBefore(this.element);=0A=
  },=0A=
=0A=
  insertContent: function(fragments) {=0A=
    fragments.each((function(fragment) {=0A=
      this.element.parentNode.insertBefore(fragment, this.element);=0A=
    }).bind(this));=0A=
  }=0A=
});=0A=
=0A=
Insertion.Top =3D Class.create();=0A=
Insertion.Top.prototype =3D Object.extend(new =
Abstract.Insertion('afterBegin'), {=0A=
  initializeRange: function() {=0A=
    this.range.selectNodeContents(this.element);=0A=
    this.range.collapse(true);=0A=
  },=0A=
=0A=
  insertContent: function(fragments) {=0A=
    fragments.reverse(false).each((function(fragment) {=0A=
      this.element.insertBefore(fragment, this.element.firstChild);=0A=
    }).bind(this));=0A=
  }=0A=
});=0A=
=0A=
Insertion.Bottom =3D Class.create();=0A=
Insertion.Bottom.prototype =3D Object.extend(new =
Abstract.Insertion('beforeEnd'), {=0A=
  initializeRange: function() {=0A=
    this.range.selectNodeContents(this.element);=0A=
    this.range.collapse(this.element);=0A=
  },=0A=
=0A=
  insertContent: function(fragments) {=0A=
    fragments.each((function(fragment) {=0A=
      this.element.appendChild(fragment);=0A=
    }).bind(this));=0A=
  }=0A=
});=0A=
=0A=
Insertion.After =3D Class.create();=0A=
Insertion.After.prototype =3D Object.extend(new =
Abstract.Insertion('afterEnd'), {=0A=
  initializeRange: function() {=0A=
    this.range.setStartAfter(this.element);=0A=
  },=0A=
=0A=
  insertContent: function(fragments) {=0A=
    fragments.each((function(fragment) {=0A=
      this.element.parentNode.insertBefore(fragment,=0A=
        this.element.nextSibling);=0A=
    }).bind(this));=0A=
  }=0A=
});=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Element.ClassNames =3D Class.create();=0A=
Element.ClassNames.prototype =3D {=0A=
  initialize: function(element) {=0A=
    this.element =3D $(element);=0A=
  },=0A=
=0A=
  _each: function(iterator) {=0A=
    this.element.className.split(/\s+/).select(function(name) {=0A=
      return name.length > 0;=0A=
    })._each(iterator);=0A=
  },=0A=
=0A=
  set: function(className) {=0A=
    this.element.className =3D className;=0A=
  },=0A=
=0A=
  add: function(classNameToAdd) {=0A=
    if (this.include(classNameToAdd)) return;=0A=
    this.set($A(this).concat(classNameToAdd).join(' '));=0A=
  },=0A=
=0A=
  remove: function(classNameToRemove) {=0A=
    if (!this.include(classNameToRemove)) return;=0A=
    this.set($A(this).without(classNameToRemove).join(' '));=0A=
  },=0A=
=0A=
  toString: function() {=0A=
    return $A(this).join(' ');=0A=
  }=0A=
};=0A=
=0A=
Object.extend(Element.ClassNames.prototype, Enumerable);=0A=
var Selector =3D Class.create();=0A=
Selector.prototype =3D {=0A=
  initialize: function(expression) {=0A=
    this.params =3D {classNames: []};=0A=
    this.expression =3D expression.toString().strip();=0A=
    this.parseExpression();=0A=
    this.compileMatcher();=0A=
  },=0A=
=0A=
  parseExpression: function() {=0A=
    function abort(message) { throw 'Parse error in selector: ' + =
message; }=0A=
=0A=
    if (this.expression =3D=3D '')  abort('empty expression');=0A=
=0A=
    var params =3D this.params, expr =3D this.expression, match, =
modifier, clause, rest;=0A=
    while (match =3D =
expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=3D)(?:"([^"]*)"|([^\]\s]*))=
)?\]$/i)) {=0A=
      params.attributes =3D params.attributes || [];=0A=
      params.attributes.push({name: match[2], operator: match[3], value: =
match[4] || match[5] || ''});=0A=
      expr =3D match[1];=0A=
    }=0A=
=0A=
    if (expr =3D=3D '*') return this.params.wildcard =3D true;=0A=
=0A=
    while (match =3D expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {=0A=
      modifier =3D match[1], clause =3D match[2], rest =3D match[3];=0A=
      switch (modifier) {=0A=
        case '#':       params.id =3D clause; break;=0A=
        case '.':       params.classNames.push(clause); break;=0A=
        case '':=0A=
        case undefined: params.tagName =3D clause.toUpperCase(); break;=0A=
        default:        abort(expr.inspect());=0A=
      }=0A=
      expr =3D rest;=0A=
    }=0A=
=0A=
    if (expr.length > 0) abort(expr.inspect());=0A=
  },=0A=
=0A=
  buildMatchExpression: function() {=0A=
    var params =3D this.params, conditions =3D [], clause;=0A=
=0A=
    if (params.wildcard)=0A=
      conditions.push('true');=0A=
    if (clause =3D params.id)=0A=
      conditions.push('element.readAttribute("id") =3D=3D ' + =
clause.inspect());=0A=
    if (clause =3D params.tagName)=0A=
      conditions.push('element.tagName.toUpperCase() =3D=3D ' + =
clause.inspect());=0A=
    if ((clause =3D params.classNames).length > 0)=0A=
      for (var i =3D 0, length =3D clause.length; i < length; i++)=0A=
        conditions.push('element.hasClassName(' + clause[i].inspect() + =
')');=0A=
    if (clause =3D params.attributes) {=0A=
      clause.each(function(attribute) {=0A=
        var value =3D 'element.readAttribute(' + =
attribute.name.inspect() + ')';=0A=
        var splitValueBy =3D function(delimiter) {=0A=
          return value + ' && ' + value + '.split(' + =
delimiter.inspect() + ')';=0A=
        }=0A=
=0A=
        switch (attribute.operator) {=0A=
          case '=3D':       conditions.push(value + ' =3D=3D ' + =
attribute.value.inspect()); break;=0A=
          case '~=3D':      conditions.push(splitValueBy(' ') + =
'.include(' + attribute.value.inspect() + ')'); break;=0A=
          case '|=3D':      conditions.push(=0A=
                            splitValueBy('-') + '.first().toUpperCase() =
=3D=3D ' + attribute.value.toUpperCase().inspect()=0A=
                          ); break;=0A=
          case '!=3D':      conditions.push(value + ' !=3D ' + =
attribute.value.inspect()); break;=0A=
          case '':=0A=
          case undefined: conditions.push('element.hasAttribute(' + =
attribute.name.inspect() + ')'); break;=0A=
          default:        throw 'Unknown operator ' + attribute.operator =
+ ' in selector';=0A=
        }=0A=
      });=0A=
    }=0A=
=0A=
    return conditions.join(' && ');=0A=
  },=0A=
=0A=
  compileMatcher: function() {=0A=
    this.match =3D new Function('element', 'if (!element.tagName) return =
false; \=0A=
      element =3D $(element); \=0A=
      return ' + this.buildMatchExpression());=0A=
  },=0A=
=0A=
  findElements: function(scope) {=0A=
    var element;=0A=
=0A=
    if (element =3D $(this.params.id))=0A=
      if (this.match(element))=0A=
        if (!scope || Element.childOf(element, scope))=0A=
          return [element];=0A=
=0A=
    scope =3D (scope || =
document).getElementsByTagName(this.params.tagName || '*');=0A=
=0A=
    var results =3D [];=0A=
    for (var i =3D 0, length =3D scope.length; i < length; i++)=0A=
      if (this.match(element =3D scope[i]))=0A=
        results.push(Element.extend(element));=0A=
=0A=
    return results;=0A=
  },=0A=
=0A=
  toString: function() {=0A=
    return this.expression;=0A=
  }=0A=
}=0A=
=0A=
Object.extend(Selector, {=0A=
  matchElements: function(elements, expression) {=0A=
    var selector =3D new Selector(expression);=0A=
    return =
elements.select(selector.match.bind(selector)).map(Element.extend);=0A=
  },=0A=
=0A=
  findElement: function(elements, expression, index) {=0A=
    if (typeof expression =3D=3D 'number') index =3D expression, =
expression =3D false;=0A=
    return Selector.matchElements(elements, expression || '*')[index || =
0];=0A=
  },=0A=
=0A=
  findChildElements: function(element, expressions) {=0A=
    return expressions.map(function(expression) {=0A=
      return =
expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], =
function(results, expr) {=0A=
        var selector =3D new Selector(expr);=0A=
        return results.inject([], function(elements, result) {=0A=
          return elements.concat(selector.findElements(result || =
element));=0A=
        });=0A=
      });=0A=
    }).flatten();=0A=
  }=0A=
});=0A=
=0A=
function $$() {=0A=
  return Selector.findChildElements(document, $A(arguments));=0A=
}=0A=
var Form =3D {=0A=
  reset: function(form) {=0A=
    $(form).reset();=0A=
    return form;=0A=
  },=0A=
=0A=
  serializeElements: function(elements, getHash) {=0A=
    var data =3D elements.inject({}, function(result, element) {=0A=
      if (!element.disabled && element.name) {=0A=
        var key =3D element.name, value =3D $(element).getValue();=0A=
        if (value !=3D undefined) {=0A=
          if (result[key]) {=0A=
            if (result[key].constructor !=3D Array) result[key] =3D =
[result[key]];=0A=
            result[key].push(value);=0A=
          }=0A=
          else result[key] =3D value;=0A=
        }=0A=
      }=0A=
      return result;=0A=
    });=0A=
=0A=
    return getHash ? data : Hash.toQueryString(data);=0A=
  }=0A=
};=0A=
=0A=
Form.Methods =3D {=0A=
  serialize: function(form, getHash) {=0A=
    return Form.serializeElements(Form.getElements(form), getHash);=0A=
  },=0A=
=0A=
  getElements: function(form) {=0A=
    return $A($(form).getElementsByTagName('*')).inject([],=0A=
      function(elements, child) {=0A=
        if (Form.Element.Serializers[child.tagName.toLowerCase()])=0A=
          elements.push(Element.extend(child));=0A=
        return elements;=0A=
      }=0A=
    );=0A=
  },=0A=
=0A=
  getInputs: function(form, typeName, name) {=0A=
    form =3D $(form);=0A=
    var inputs =3D form.getElementsByTagName('input');=0A=
=0A=
    if (!typeName && !name) return $A(inputs).map(Element.extend);=0A=
=0A=
    for (var i =3D 0, matchingInputs =3D [], length =3D inputs.length; i =
< length; i++) {=0A=
      var input =3D inputs[i];=0A=
      if ((typeName && input.type !=3D typeName) || (name && input.name =
!=3D name))=0A=
        continue;=0A=
      matchingInputs.push(Element.extend(input));=0A=
    }=0A=
=0A=
    return matchingInputs;=0A=
  },=0A=
=0A=
  disable: function(form) {=0A=
    form =3D $(form);=0A=
    form.getElements().each(function(element) {=0A=
      element.blur();=0A=
      element.disabled =3D 'true';=0A=
    });=0A=
    return form;=0A=
  },=0A=
=0A=
  enable: function(form) {=0A=
    form =3D $(form);=0A=
    form.getElements().each(function(element) {=0A=
      element.disabled =3D '';=0A=
    });=0A=
    return form;=0A=
  },=0A=
=0A=
  findFirstElement: function(form) {=0A=
    return $(form).getElements().find(function(element) {=0A=
      return element.type !=3D 'hidden' && !element.disabled &&=0A=
        ['input', 'select', =
'textarea'].include(element.tagName.toLowerCase());=0A=
    });=0A=
  },=0A=
=0A=
  focusFirstElement: function(form) {=0A=
    form =3D $(form);=0A=
    form.findFirstElement().activate();=0A=
    return form;=0A=
  }=0A=
}=0A=
=0A=
Object.extend(Form, Form.Methods);=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Form.Element =3D {=0A=
  focus: function(element) {=0A=
    $(element).focus();=0A=
    return element;=0A=
  },=0A=
=0A=
  select: function(element) {=0A=
    $(element).select();=0A=
    return element;=0A=
  }=0A=
}=0A=
=0A=
Form.Element.Methods =3D {=0A=
  serialize: function(element) {=0A=
    element =3D $(element);=0A=
    if (!element.disabled && element.name) {=0A=
      var value =3D element.getValue();=0A=
      if (value !=3D undefined) {=0A=
        var pair =3D {};=0A=
        pair[element.name] =3D value;=0A=
        return Hash.toQueryString(pair);=0A=
      }=0A=
    }=0A=
    return '';=0A=
  },=0A=
=0A=
  getValue: function(element) {=0A=
    element =3D $(element);=0A=
    var method =3D element.tagName.toLowerCase();=0A=
    return Form.Element.Serializers[method](element);=0A=
  },=0A=
=0A=
  clear: function(element) {=0A=
    $(element).value =3D '';=0A=
    return element;=0A=
  },=0A=
=0A=
  present: function(element) {=0A=
    return $(element).value !=3D '';=0A=
  },=0A=
=0A=
  activate: function(element) {=0A=
    element =3D $(element);=0A=
    element.focus();=0A=
    if (element.select && ( element.tagName.toLowerCase() !=3D 'input' ||=0A=
      !['button', 'reset', 'submit'].include(element.type) ) )=0A=
      element.select();=0A=
    return element;=0A=
  },=0A=
=0A=
  disable: function(element) {=0A=
    element =3D $(element);=0A=
    element.disabled =3D true;=0A=
    return element;=0A=
  },=0A=
=0A=
  enable: function(element) {=0A=
    element =3D $(element);=0A=
    element.blur();=0A=
    element.disabled =3D false;=0A=
    return element;=0A=
  }=0A=
}=0A=
=0A=
Object.extend(Form.Element, Form.Element.Methods);=0A=
var Field =3D Form.Element;=0A=
var $F =3D Form.Element.getValue;=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Form.Element.Serializers =3D {=0A=
  input: function(element) {=0A=
    switch (element.type.toLowerCase()) {=0A=
      case 'checkbox':=0A=
      case 'radio':=0A=
        return Form.Element.Serializers.inputSelector(element);=0A=
      default:=0A=
        return Form.Element.Serializers.textarea(element);=0A=
    }=0A=
  },=0A=
=0A=
  inputSelector: function(element) {=0A=
    return element.checked ? element.value : null;=0A=
  },=0A=
=0A=
  textarea: function(element) {=0A=
    return element.value;=0A=
  },=0A=
=0A=
  select: function(element) {=0A=
    return this[element.type =3D=3D 'select-one' ?=0A=
      'selectOne' : 'selectMany'](element);=0A=
  },=0A=
=0A=
  selectOne: function(element) {=0A=
    var index =3D element.selectedIndex;=0A=
    return index >=3D 0 ? this.optionValue(element.options[index]) : =
null;=0A=
  },=0A=
=0A=
  selectMany: function(element) {=0A=
    var values, length =3D element.length;=0A=
    if (!length) return null;=0A=
=0A=
    for (var i =3D 0, values =3D []; i < length; i++) {=0A=
      var opt =3D element.options[i];=0A=
      if (opt.selected) values.push(this.optionValue(opt));=0A=
    }=0A=
    return values;=0A=
  },=0A=
=0A=
  optionValue: function(opt) {=0A=
    // extend element because hasAttribute may not be native=0A=
    return Element.extend(opt).hasAttribute('value') ? opt.value : =
opt.text;=0A=
  }=0A=
}=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Abstract.TimedObserver =3D function() {}=0A=
Abstract.TimedObserver.prototype =3D {=0A=
  initialize: function(element, frequency, callback) {=0A=
    this.frequency =3D frequency;=0A=
    this.element   =3D $(element);=0A=
    this.callback  =3D callback;=0A=
=0A=
    this.lastValue =3D this.getValue();=0A=
    this.registerCallback();=0A=
  },=0A=
=0A=
  registerCallback: function() {=0A=
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);=0A=
  },=0A=
=0A=
  onTimerEvent: function() {=0A=
    var value =3D this.getValue();=0A=
    var changed =3D ('string' =3D=3D typeof this.lastValue && 'string' =
=3D=3D typeof value=0A=
      ? this.lastValue !=3D value : String(this.lastValue) !=3D =
String(value));=0A=
    if (changed) {=0A=
      this.callback(this.element, value);=0A=
      this.lastValue =3D value;=0A=
    }=0A=
  }=0A=
}=0A=
=0A=
Form.Element.Observer =3D Class.create();=0A=
Form.Element.Observer.prototype =3D Object.extend(new =
Abstract.TimedObserver(), {=0A=
  getValue: function() {=0A=
    return Form.Element.getValue(this.element);=0A=
  }=0A=
});=0A=
=0A=
Form.Observer =3D Class.create();=0A=
Form.Observer.prototype =3D Object.extend(new Abstract.TimedObserver(), {=0A=
  getValue: function() {=0A=
    return Form.serialize(this.element);=0A=
  }=0A=
});=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Abstract.EventObserver =3D function() {}=0A=
Abstract.EventObserver.prototype =3D {=0A=
  initialize: function(element, callback) {=0A=
    this.element  =3D $(element);=0A=
    this.callback =3D callback;=0A=
=0A=
    this.lastValue =3D this.getValue();=0A=
    if (this.element.tagName.toLowerCase() =3D=3D 'form')=0A=
      this.registerFormCallbacks();=0A=
    else=0A=
      this.registerCallback(this.element);=0A=
  },=0A=
=0A=
  onElementEvent: function() {=0A=
    var value =3D this.getValue();=0A=
    if (this.lastValue !=3D value) {=0A=
      this.callback(this.element, value);=0A=
      this.lastValue =3D value;=0A=
    }=0A=
  },=0A=
=0A=
  registerFormCallbacks: function() {=0A=
    =
Form.getElements(this.element).each(this.registerCallback.bind(this));=0A=
  },=0A=
=0A=
  registerCallback: function(element) {=0A=
    if (element.type) {=0A=
      switch (element.type.toLowerCase()) {=0A=
        case 'checkbox':=0A=
        case 'radio':=0A=
          Event.observe(element, 'click', =
this.onElementEvent.bind(this));=0A=
          break;=0A=
        default:=0A=
          Event.observe(element, 'change', =
this.onElementEvent.bind(this));=0A=
          break;=0A=
      }=0A=
    }=0A=
  }=0A=
}=0A=
=0A=
Form.Element.EventObserver =3D Class.create();=0A=
Form.Element.EventObserver.prototype =3D Object.extend(new =
Abstract.EventObserver(), {=0A=
  getValue: function() {=0A=
    return Form.Element.getValue(this.element);=0A=
  }=0A=
});=0A=
=0A=
Form.EventObserver =3D Class.create();=0A=
Form.EventObserver.prototype =3D Object.extend(new =
Abstract.EventObserver(), {=0A=
  getValue: function() {=0A=
    return Form.serialize(this.element);=0A=
  }=0A=
});=0A=
if (!window.Event) {=0A=
  var Event =3D new Object();=0A=
}=0A=
=0A=
Object.extend(Event, {=0A=
  KEY_BACKSPACE: 8,=0A=
  KEY_TAB:       9,=0A=
  KEY_RETURN:   13,=0A=
  KEY_ESC:      27,=0A=
  KEY_LEFT:     37,=0A=
  KEY_UP:       38,=0A=
  KEY_RIGHT:    39,=0A=
  KEY_DOWN:     40,=0A=
  KEY_DELETE:   46,=0A=
  KEY_HOME:     36,=0A=
  KEY_END:      35,=0A=
  KEY_PAGEUP:   33,=0A=
  KEY_PAGEDOWN: 34,=0A=
=0A=
  element: function(event) {=0A=
    return event.target || event.srcElement;=0A=
  },=0A=
=0A=
  isLeftClick: function(event) {=0A=
    return (((event.which) && (event.which =3D=3D 1)) ||=0A=
            ((event.button) && (event.button =3D=3D 1)));=0A=
  },=0A=
=0A=
  pointerX: function(event) {=0A=
    return event.pageX || (event.clientX +=0A=
      (document.documentElement.scrollLeft || document.body.scrollLeft));=0A=
  },=0A=
=0A=
  pointerY: function(event) {=0A=
    return event.pageY || (event.clientY +=0A=
      (document.documentElement.scrollTop || document.body.scrollTop));=0A=
  },=0A=
=0A=
  stop: function(event) {=0A=
    if (event.preventDefault) {=0A=
      event.preventDefault();=0A=
      event.stopPropagation();=0A=
    } else {=0A=
      event.returnValue =3D false;=0A=
      event.cancelBubble =3D true;=0A=
    }=0A=
  },=0A=
=0A=
  // find the first node with the given tagName, starting from the=0A=
  // node the event was triggered on; traverses the DOM upwards=0A=
  findElement: function(event, tagName) {=0A=
    var element =3D Event.element(event);=0A=
    while (element.parentNode && (!element.tagName ||=0A=
        (element.tagName.toUpperCase() !=3D tagName.toUpperCase())))=0A=
      element =3D element.parentNode;=0A=
    return element;=0A=
  },=0A=
=0A=
  observers: false,=0A=
=0A=
  _observeAndCache: function(element, name, observer, useCapture) {=0A=
    if (!this.observers) this.observers =3D [];=0A=
    if (element.addEventListener) {=0A=
      this.observers.push([element, name, observer, useCapture]);=0A=
      element.addEventListener(name, observer, useCapture);=0A=
    } else if (element.attachEvent) {=0A=
      this.observers.push([element, name, observer, useCapture]);=0A=
      element.attachEvent('on' + name, observer);=0A=
    }=0A=
  },=0A=
=0A=
  unloadCache: function() {=0A=
    if (!Event.observers) return;=0A=
    for (var i =3D 0, length =3D Event.observers.length; i < length; =
i++) {=0A=
      Event.stopObserving.apply(this, Event.observers[i]);=0A=
      Event.observers[i][0] =3D null;=0A=
    }=0A=
    Event.observers =3D false;=0A=
  },=0A=
=0A=
  observe: function(element, name, observer, useCapture) {=0A=
    element =3D $(element);=0A=
    useCapture =3D useCapture || false;=0A=
=0A=
    if (name =3D=3D 'keypress' &&=0A=
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)=0A=
        || element.attachEvent))=0A=
      name =3D 'keydown';=0A=
=0A=
    Event._observeAndCache(element, name, observer, useCapture);=0A=
  },=0A=
=0A=
  stopObserving: function(element, name, observer, useCapture) {=0A=
    element =3D $(element);=0A=
    useCapture =3D useCapture || false;=0A=
=0A=
    if (name =3D=3D 'keypress' &&=0A=
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)=0A=
        || element.detachEvent))=0A=
      name =3D 'keydown';=0A=
=0A=
    if (element.removeEventListener) {=0A=
      element.removeEventListener(name, observer, useCapture);=0A=
    } else if (element.detachEvent) {=0A=
      try {=0A=
        element.detachEvent('on' + name, observer);=0A=
      } catch (e) {}=0A=
    }=0A=
  }=0A=
});=0A=
=0A=
/* prevent memory leaks in IE */=0A=
if (navigator.appVersion.match(/\bMSIE\b/))=0A=
  Event.observe(window, 'unload', Event.unloadCache, false);=0A=
var Position =3D {=0A=
  // set to true if needed, warning: firefox performance problems=0A=
  // NOT neeeded for page scrolling, only if draggable contained in=0A=
  // scrollable elements=0A=
  includeScrollOffsets: false,=0A=
=0A=
  // must be called before calling withinIncludingScrolloffset, every =
time the=0A=
  // page is scrolled=0A=
  prepare: function() {=0A=
    this.deltaX =3D  window.pageXOffset=0A=
                || document.documentElement.scrollLeft=0A=
                || document.body.scrollLeft=0A=
                || 0;=0A=
    this.deltaY =3D  window.pageYOffset=0A=
                || document.documentElement.scrollTop=0A=
                || document.body.scrollTop=0A=
                || 0;=0A=
  },=0A=
=0A=
  realOffset: function(element) {=0A=
    var valueT =3D 0, valueL =3D 0;=0A=
    do {=0A=
      valueT +=3D element.scrollTop  || 0;=0A=
      valueL +=3D element.scrollLeft || 0;=0A=
      element =3D element.parentNode;=0A=
    } while (element);=0A=
    return [valueL, valueT];=0A=
  },=0A=
=0A=
  cumulativeOffset: function(element) {=0A=
    var valueT =3D 0, valueL =3D 0;=0A=
    do {=0A=
      valueT +=3D element.offsetTop  || 0;=0A=
      valueL +=3D element.offsetLeft || 0;=0A=
      element =3D element.offsetParent;=0A=
    } while (element);=0A=
    return [valueL, valueT];=0A=
  },=0A=
=0A=
  positionedOffset: function(element) {=0A=
    var valueT =3D 0, valueL =3D 0;=0A=
    do {=0A=
      valueT +=3D element.offsetTop  || 0;=0A=
      valueL +=3D element.offsetLeft || 0;=0A=
      element =3D element.offsetParent;=0A=
      if (element) {=0A=
        if(element.tagName=3D=3D'BODY') break;=0A=
        var p =3D Element.getStyle(element, 'position');=0A=
        if (p =3D=3D 'relative' || p =3D=3D 'absolute') break;=0A=
      }=0A=
    } while (element);=0A=
    return [valueL, valueT];=0A=
  },=0A=
=0A=
  offsetParent: function(element) {=0A=
    if (element.offsetParent) return element.offsetParent;=0A=
    if (element =3D=3D document.body) return element;=0A=
=0A=
    while ((element =3D element.parentNode) && element !=3D =
document.body)=0A=
      if (Element.getStyle(element, 'position') !=3D 'static')=0A=
        return element;=0A=
=0A=
    return document.body;=0A=
  },=0A=
=0A=
  // caches x/y coordinate pair to use with overlap=0A=
  within: function(element, x, y) {=0A=
    if (this.includeScrollOffsets)=0A=
      return this.withinIncludingScrolloffsets(element, x, y);=0A=
    this.xcomp =3D x;=0A=
    this.ycomp =3D y;=0A=
    this.offset =3D this.cumulativeOffset(element);=0A=
=0A=
    return (y >=3D this.offset[1] &&=0A=
            y <  this.offset[1] + element.offsetHeight &&=0A=
            x >=3D this.offset[0] &&=0A=
            x <  this.offset[0] + element.offsetWidth);=0A=
  },=0A=
=0A=
  withinIncludingScrolloffsets: function(element, x, y) {=0A=
    var offsetcache =3D this.realOffset(element);=0A=
=0A=
    this.xcomp =3D x + offsetcache[0] - this.deltaX;=0A=
    this.ycomp =3D y + offsetcache[1] - this.deltaY;=0A=
    this.offset =3D this.cumulativeOffset(element);=0A=
=0A=
    return (this.ycomp >=3D this.offset[1] &&=0A=
            this.ycomp <  this.offset[1] + element.offsetHeight &&=0A=
            this.xcomp >=3D this.offset[0] &&=0A=
            this.xcomp <  this.offset[0] + element.offsetWidth);=0A=
  },=0A=
=0A=
  // within must be called directly before=0A=
  overlap: function(mode, element) {=0A=
    if (!mode) return 0;=0A=
    if (mode =3D=3D 'vertical')=0A=
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /=0A=
        element.offsetHeight;=0A=
    if (mode =3D=3D 'horizontal')=0A=
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /=0A=
        element.offsetWidth;=0A=
  },=0A=
=0A=
  page: function(forElement) {=0A=
    var valueT =3D 0, valueL =3D 0;=0A=
=0A=
    var element =3D forElement;=0A=
    do {=0A=
      valueT +=3D element.offsetTop  || 0;=0A=
      valueL +=3D element.offsetLeft || 0;=0A=
=0A=
      // Safari fix=0A=
      if (element.offsetParent=3D=3Ddocument.body)=0A=
        if (Element.getStyle(element,'position')=3D=3D'absolute') break;=0A=
=0A=
    } while (element =3D element.offsetParent);=0A=
=0A=
    element =3D forElement;=0A=
    do {=0A=
      if (!window.opera || element.tagName=3D=3D'BODY') {=0A=
        valueT -=3D element.scrollTop  || 0;=0A=
        valueL -=3D element.scrollLeft || 0;=0A=
      }=0A=
    } while (element =3D element.parentNode);=0A=
=0A=
    return [valueL, valueT];=0A=
  },=0A=
=0A=
  clone: function(source, target) {=0A=
    var options =3D Object.extend({=0A=
      setLeft:    true,=0A=
      setTop:     true,=0A=
      setWidth:   true,=0A=
      setHeight:  true,=0A=
      offsetTop:  0,=0A=
      offsetLeft: 0=0A=
    }, arguments[2] || {})=0A=
=0A=
    // find page position of source=0A=
    source =3D $(source);=0A=
    var p =3D Position.page(source);=0A=
=0A=
    // find coordinate system to use=0A=
    target =3D $(target);=0A=
    var delta =3D [0, 0];=0A=
    var parent =3D null;=0A=
    // delta [0,0] will do fine with position: fixed elements,=0A=
    // position:absolute needs offsetParent deltas=0A=
    if (Element.getStyle(target,'position') =3D=3D 'absolute') {=0A=
      parent =3D Position.offsetParent(target);=0A=
      delta =3D Position.page(parent);=0A=
    }=0A=
=0A=
    // correct by body offsets (fixes Safari)=0A=
    if (parent =3D=3D document.body) {=0A=
      delta[0] -=3D document.body.offsetLeft;=0A=
      delta[1] -=3D document.body.offsetTop;=0A=
    }=0A=
=0A=
    // set position=0A=
    if(options.setLeft)   target.style.left  =3D (p[0] - delta[0] + =
options.offsetLeft) + 'px';=0A=
    if(options.setTop)    target.style.top   =3D (p[1] - delta[1] + =
options.offsetTop) + 'px';=0A=
    if(options.setWidth)  target.style.width =3D source.offsetWidth + =
'px';=0A=
    if(options.setHeight) target.style.height =3D source.offsetHeight + =
'px';=0A=
  },=0A=
=0A=
  absolutize: function(element) {=0A=
    element =3D $(element);=0A=
    if (element.style.position =3D=3D 'absolute') return;=0A=
    Position.prepare();=0A=
=0A=
    var offsets =3D Position.positionedOffset(element);=0A=
    var top     =3D offsets[1];=0A=
    var left    =3D offsets[0];=0A=
    var width   =3D element.clientWidth;=0A=
    var height  =3D element.clientHeight;=0A=
=0A=
    element._originalLeft   =3D left - parseFloat(element.style.left  || =
0);=0A=
    element._originalTop    =3D top  - parseFloat(element.style.top || =
0);=0A=
    element._originalWidth  =3D element.style.width;=0A=
    element._originalHeight =3D element.style.height;=0A=
=0A=
    element.style.position =3D 'absolute';=0A=
    element.style.top    =3D top + 'px';=0A=
    element.style.left   =3D left + 'px';=0A=
    element.style.width  =3D width + 'px';=0A=
    element.style.height =3D height + 'px';=0A=
  },=0A=
=0A=
  relativize: function(element) {=0A=
    element =3D $(element);=0A=
    if (element.style.position =3D=3D 'relative') return;=0A=
    Position.prepare();=0A=
=0A=
    element.style.position =3D 'relative';=0A=
    var top  =3D parseFloat(element.style.top  || 0) - =
(element._originalTop || 0);=0A=
    var left =3D parseFloat(element.style.left || 0) - =
(element._originalLeft || 0);=0A=
=0A=
    element.style.top    =3D top + 'px';=0A=
    element.style.left   =3D left + 'px';=0A=
    element.style.height =3D element._originalHeight;=0A=
    element.style.width  =3D element._originalWidth;=0A=
  }=0A=
}=0A=
=0A=
// Safari returns margins on body which is incorrect if the child is =
absolutely=0A=
// positioned.  For performance reasons, redefine =
Position.cumulativeOffset for=0A=
// KHTML/WebKit only.=0A=
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {=0A=
  Position.cumulativeOffset =3D function(element) {=0A=
    var valueT =3D 0, valueL =3D 0;=0A=
    do {=0A=
      valueT +=3D element.offsetTop  || 0;=0A=
      valueL +=3D element.offsetLeft || 0;=0A=
      if (element.offsetParent =3D=3D document.body)=0A=
        if (Element.getStyle(element, 'position') =3D=3D 'absolute') =
break;=0A=
=0A=
      element =3D element.offsetParent;=0A=
    } while (element);=0A=
=0A=
    return [valueL, valueT];=0A=
  }=0A=
}=0A=
=0A=
Element.addMethods();
------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/effects.js?1209768151

// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, =
http://mir.aculo.us)=0A=
// Contributors:=0A=
//  Justin Palmer (http://encytemedia.com/)=0A=
//  Mark Pilgrim (http://diveintomark.org/)=0A=
//  Martin Bialasinki=0A=
// =0A=
// script.aculo.us is freely distributable under the terms of an =
MIT-style license.=0A=
// For details, see the script.aculo.us web site: =
http://script.aculo.us/ =0A=
=0A=
// converts rgb() and #xxx to #xxxxxx format,  =0A=
// returns self (or first argument) if not convertable  =0A=
String.prototype.parseColor =3D function() {  =0A=
  var color =3D '#';=0A=
  if(this.slice(0,4) =3D=3D 'rgb(') {  =0A=
    var cols =3D this.slice(4,this.length-1).split(',');  =0A=
    var i=3D0; do { color +=3D parseInt(cols[i]).toColorPart() } while =
(++i<3);  =0A=
  } else {  =0A=
    if(this.slice(0,1) =3D=3D '#') {  =0A=
      if(this.length=3D=3D4) for(var i=3D1;i<4;i++) color +=3D =
(this.charAt(i) + this.charAt(i)).toLowerCase();  =0A=
      if(this.length=3D=3D7) color =3D this.toLowerCase();  =0A=
    }  =0A=
  }  =0A=
  return(color.length=3D=3D7 ? color : (arguments[0] || this));  =0A=
}=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Element.collectTextNodes =3D function(element) {  =0A=
  return $A($(element).childNodes).collect( function(node) {=0A=
    return (node.nodeType=3D=3D3 ? node.nodeValue : =0A=
      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));=0A=
  }).flatten().join('');=0A=
}=0A=
=0A=
Element.collectTextNodesIgnoreClass =3D function(element, className) {  =0A=
  return $A($(element).childNodes).collect( function(node) {=0A=
    return (node.nodeType=3D=3D3 ? node.nodeValue : =0A=
      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? =0A=
        Element.collectTextNodesIgnoreClass(node, className) : ''));=0A=
  }).flatten().join('');=0A=
}=0A=
=0A=
Element.setContentZoom =3D function(element, percent) {=0A=
  element =3D $(element);  =0A=
  element.setStyle({fontSize: (percent/100) + 'em'});   =0A=
  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);=0A=
  return element;=0A=
}=0A=
=0A=
Element.getOpacity =3D function(element){=0A=
  element =3D $(element);=0A=
  var opacity;=0A=
  if (opacity =3D element.getStyle('opacity'))  =0A=
    return parseFloat(opacity);  =0A=
  if (opacity =3D (element.getStyle('filter') || =
'').match(/alpha\(opacity=3D(.*)\)/))  =0A=
    if(opacity[1]) return parseFloat(opacity[1]) / 100;  =0A=
  return 1.0;  =0A=
}=0A=
=0A=
Element.setOpacity =3D function(element, value){  =0A=
  element=3D $(element);  =0A=
  if (value =3D=3D 1){=0A=
    element.setStyle({ opacity: =0A=
      (/Gecko/.test(navigator.userAgent) && =
!/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? =0A=
      0.999999 : 1.0 });=0A=
    if(/MSIE/.test(navigator.userAgent) && !window.opera)  =0A=
      element.setStyle({filter: =
Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  =0A=
  } else {  =0A=
    if(value < 0.00001) value =3D 0;  =0A=
    element.setStyle({opacity: value});=0A=
    if(/MSIE/.test(navigator.userAgent) && !window.opera)  =0A=
      element.setStyle(=0A=
        { filter: =
element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +=0A=
            'alpha(opacity=3D'+value*100+')' });  =0A=
  }=0A=
  return element;=0A=
}  =0A=
 =0A=
Element.getInlineOpacity =3D function(element){  =0A=
  return $(element).style.opacity || '';=0A=
}  =0A=
=0A=
Element.forceRerendering =3D function(element) {=0A=
  try {=0A=
    element =3D $(element);=0A=
    var n =3D document.createTextNode(' ');=0A=
    element.appendChild(n);=0A=
    element.removeChild(n);=0A=
  } catch(e) { }=0A=
};=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
Array.prototype.call =3D function() {=0A=
  var args =3D arguments;=0A=
  this.each(function(f){ f.apply(this, args) });=0A=
}=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
var Effect =3D {=0A=
  _elementDoesNotExistError: {=0A=
    name: 'ElementDoesNotExistError',=0A=
    message: 'The specified DOM element does not exist, but is required =
for this effect to operate'=0A=
  },=0A=
  tagifyText: function(element) {=0A=
    if(typeof Builder =3D=3D 'undefined')=0A=
      throw("Effect.tagifyText requires including script.aculo.us' =
builder.js library");=0A=
      =0A=
    var tagifyStyle =3D 'position:relative';=0A=
    if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle =
+=3D ';zoom:1';=0A=
    =0A=
    element =3D $(element);=0A=
    $A(element.childNodes).each( function(child) {=0A=
      if(child.nodeType=3D=3D3) {=0A=
        child.nodeValue.toArray().each( function(character) {=0A=
          element.insertBefore(=0A=
            Builder.node('span',{style: tagifyStyle},=0A=
              character =3D=3D ' ' ? String.fromCharCode(160) : =
character), =0A=
              child);=0A=
        });=0A=
        Element.remove(child);=0A=
      }=0A=
    });=0A=
  },=0A=
  multiple: function(element, effect) {=0A=
    var elements;=0A=
    if(((typeof element =3D=3D 'object') || =0A=
        (typeof element =3D=3D 'function')) && =0A=
       (element.length))=0A=
      elements =3D element;=0A=
    else=0A=
      elements =3D $(element).childNodes;=0A=
      =0A=
    var options =3D Object.extend({=0A=
      speed: 0.1,=0A=
      delay: 0.0=0A=
    }, arguments[2] || {});=0A=
    var masterDelay =3D options.delay;=0A=
=0A=
    $A(elements).each( function(element, index) {=0A=
      new effect(element, Object.extend(options, { delay: index * =
options.speed + masterDelay }));=0A=
    });=0A=
  },=0A=
  PAIRS: {=0A=
    'slide':  ['SlideDown','SlideUp'],=0A=
    'blind':  ['BlindDown','BlindUp'],=0A=
    'appear': ['Appear','Fade']=0A=
  },=0A=
  toggle: function(element, effect) {=0A=
    element =3D $(element);=0A=
    effect =3D (effect || 'appear').toLowerCase();=0A=
    var options =3D Object.extend({=0A=
      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }=0A=
    }, arguments[2] || {});=0A=
    Effect[element.visible() ? =0A=
      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, =
options);=0A=
  }=0A=
};=0A=
=0A=
var Effect2 =3D Effect; // deprecated=0A=
=0A=
/* ------------- transitions ------------- */=0A=
=0A=
Effect.Transitions =3D {=0A=
  linear: Prototype.K,=0A=
  sinoidal: function(pos) {=0A=
    return (-Math.cos(pos*Math.PI)/2) + 0.5;=0A=
  },=0A=
  reverse: function(pos) {=0A=
    return 1-pos;=0A=
  },=0A=
  flicker: function(pos) {=0A=
    return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;=0A=
  },=0A=
  wobble: function(pos) {=0A=
    return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;=0A=
  },=0A=
  pulse: function(pos, pulses) { =0A=
    pulses =3D pulses || 5; =0A=
    return (=0A=
      Math.round((pos % (1/pulses)) * pulses) =3D=3D 0 ? =0A=
            ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : =0A=
        1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))=0A=
      );=0A=
  },=0A=
  none: function(pos) {=0A=
    return 0;=0A=
  },=0A=
  full: function(pos) {=0A=
    return 1;=0A=
  }=0A=
};=0A=
=0A=
/* ------------- core effects ------------- */=0A=
=0A=
Effect.ScopedQueue =3D Class.create();=0A=
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {=0A=
  initialize: function() {=0A=
    this.effects  =3D [];=0A=
    this.interval =3D null;=0A=
  },=0A=
  _each: function(iterator) {=0A=
    this.effects._each(iterator);=0A=
  },=0A=
  add: function(effect) {=0A=
    var timestamp =3D new Date().getTime();=0A=
    =0A=
    var position =3D (typeof effect.options.queue =3D=3D 'string') ? =0A=
      effect.options.queue : effect.options.queue.position;=0A=
    =0A=
    switch(position) {=0A=
      case 'front':=0A=
        // move unstarted effects after this effect  =0A=
        this.effects.findAll(function(e){ return e.state=3D=3D'idle' =
}).each( function(e) {=0A=
            e.startOn  +=3D effect.finishOn;=0A=
            e.finishOn +=3D effect.finishOn;=0A=
          });=0A=
        break;=0A=
      case 'with-last':=0A=
        timestamp =3D this.effects.pluck('startOn').max() || timestamp;=0A=
        break;=0A=
      case 'end':=0A=
        // start effect after last queued effect has finished=0A=
        timestamp =3D this.effects.pluck('finishOn').max() || timestamp;=0A=
        break;=0A=
    }=0A=
    =0A=
    effect.startOn  +=3D timestamp;=0A=
    effect.finishOn +=3D timestamp;=0A=
=0A=
    if(!effect.options.queue.limit || (this.effects.length < =
effect.options.queue.limit))=0A=
      this.effects.push(effect);=0A=
    =0A=
    if(!this.interval) =0A=
      this.interval =3D setInterval(this.loop.bind(this), 40);=0A=
  },=0A=
  remove: function(effect) {=0A=
    this.effects =3D this.effects.reject(function(e) { return =
e=3D=3Deffect });=0A=
    if(this.effects.length =3D=3D 0) {=0A=
      clearInterval(this.interval);=0A=
      this.interval =3D null;=0A=
    }=0A=
  },=0A=
  loop: function() {=0A=
    var timePos =3D new Date().getTime();=0A=
    this.effects.invoke('loop', timePos);=0A=
  }=0A=
});=0A=
=0A=
Effect.Queues =3D {=0A=
  instances: $H(),=0A=
  get: function(queueName) {=0A=
    if(typeof queueName !=3D 'string') return queueName;=0A=
    =0A=
    if(!this.instances[queueName])=0A=
      this.instances[queueName] =3D new Effect.ScopedQueue();=0A=
      =0A=
    return this.instances[queueName];=0A=
  }=0A=
}=0A=
Effect.Queue =3D Effect.Queues.get('global');=0A=
=0A=
Effect.DefaultOptions =3D {=0A=
  transition: Effect.Transitions.sinoidal,=0A=
  duration:   1.0,   // seconds=0A=
  fps:        25.0,  // max. 25fps due to Effect.Queue implementation=0A=
  sync:       false, // true for combining=0A=
  from:       0.0,=0A=
  to:         1.0,=0A=
  delay:      0.0,=0A=
  queue:      'parallel'=0A=
}=0A=
=0A=
Effect.Base =3D function() {};=0A=
Effect.Base.prototype =3D {=0A=
  position: null,=0A=
  start: function(options) {=0A=
    this.options      =3D =
Object.extend(Object.extend({},Effect.DefaultOptions), options || {});=0A=
    this.currentFrame =3D 0;=0A=
    this.state        =3D 'idle';=0A=
    this.startOn      =3D this.options.delay*1000;=0A=
    this.finishOn     =3D this.startOn + (this.options.duration*1000);=0A=
    this.event('beforeStart');=0A=
    if(!this.options.sync)=0A=
      Effect.Queues.get(typeof this.options.queue =3D=3D 'string' ? =0A=
        'global' : this.options.queue.scope).add(this);=0A=
  },=0A=
  loop: function(timePos) {=0A=
    if(timePos >=3D this.startOn) {=0A=
      if(timePos >=3D this.finishOn) {=0A=
        this.render(1.0);=0A=
        this.cancel();=0A=
        this.event('beforeFinish');=0A=
        if(this.finish) this.finish(); =0A=
        this.event('afterFinish');=0A=
        return;  =0A=
      }=0A=
      var pos   =3D (timePos - this.startOn) / (this.finishOn - =
this.startOn);=0A=
      var frame =3D Math.round(pos * this.options.fps * =
this.options.duration);=0A=
      if(frame > this.currentFrame) {=0A=
        this.render(pos);=0A=
        this.currentFrame =3D frame;=0A=
      }=0A=
    }=0A=
  },=0A=
  render: function(pos) {=0A=
    if(this.state =3D=3D 'idle') {=0A=
      this.state =3D 'running';=0A=
      this.event('beforeSetup');=0A=
      if(this.setup) this.setup();=0A=
      this.event('afterSetup');=0A=
    }=0A=
    if(this.state =3D=3D 'running') {=0A=
      if(this.options.transition) pos =3D this.options.transition(pos);=0A=
      pos *=3D (this.options.to-this.options.from);=0A=
      pos +=3D this.options.from;=0A=
      this.position =3D pos;=0A=
      this.event('beforeUpdate');=0A=
      if(this.update) this.update(pos);=0A=
      this.event('afterUpdate');=0A=
    }=0A=
  },=0A=
  cancel: function() {=0A=
    if(!this.options.sync)=0A=
      Effect.Queues.get(typeof this.options.queue =3D=3D 'string' ? =0A=
        'global' : this.options.queue.scope).remove(this);=0A=
    this.state =3D 'finished';=0A=
  },=0A=
  event: function(eventName) {=0A=
    if(this.options[eventName + 'Internal']) this.options[eventName + =
'Internal'](this);=0A=
    if(this.options[eventName]) this.options[eventName](this);=0A=
  },=0A=
  inspect: function() {=0A=
    return '#<Effect:' + $H(this).inspect() + ',options:' + =
$H(this.options).inspect() + '>';=0A=
  }=0A=
}=0A=
=0A=
Effect.Parallel =3D Class.create();=0A=
Object.extend(Object.extend(Effect.Parallel.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function(effects) {=0A=
    this.effects =3D effects || [];=0A=
    this.start(arguments[1]);=0A=
  },=0A=
  update: function(position) {=0A=
    this.effects.invoke('render', position);=0A=
  },=0A=
  finish: function(position) {=0A=
    this.effects.each( function(effect) {=0A=
      effect.render(1.0);=0A=
      effect.cancel();=0A=
      effect.event('beforeFinish');=0A=
      if(effect.finish) effect.finish(position);=0A=
      effect.event('afterFinish');=0A=
    });=0A=
  }=0A=
});=0A=
=0A=
Effect.Event =3D Class.create();=0A=
Object.extend(Object.extend(Effect.Event.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function() {=0A=
    var options =3D Object.extend({=0A=
      duration: 0=0A=
    }, arguments[0] || {});=0A=
    this.start(options);=0A=
  },=0A=
  update: Prototype.emptyFunction=0A=
});=0A=
=0A=
Effect.Opacity =3D Class.create();=0A=
Object.extend(Object.extend(Effect.Opacity.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function(element) {=0A=
    this.element =3D $(element);=0A=
    if(!this.element) throw(Effect._elementDoesNotExistError);=0A=
    // make this work on IE on elements without 'layout'=0A=
    if(/MSIE/.test(navigator.userAgent) && !window.opera && =
(!this.element.currentStyle.hasLayout))=0A=
      this.element.setStyle({zoom: 1});=0A=
    var options =3D Object.extend({=0A=
      from: this.element.getOpacity() || 0.0,=0A=
      to:   1.0=0A=
    }, arguments[1] || {});=0A=
    this.start(options);=0A=
  },=0A=
  update: function(position) {=0A=
    this.element.setOpacity(position);=0A=
  }=0A=
});=0A=
=0A=
Effect.Move =3D Class.create();=0A=
Object.extend(Object.extend(Effect.Move.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function(element) {=0A=
    this.element =3D $(element);=0A=
    if(!this.element) throw(Effect._elementDoesNotExistError);=0A=
    var options =3D Object.extend({=0A=
      x:    0,=0A=
      y:    0,=0A=
      mode: 'relative'=0A=
    }, arguments[1] || {});=0A=
    this.start(options);=0A=
  },=0A=
  setup: function() {=0A=
    // Bug in Opera: Opera returns the "real" position of a static =
element or=0A=
    // relative element that does not have top/left explicitly set.=0A=
    // =3D=3D> Always set top and left for position relative elements in =
your stylesheets =0A=
    // (to 0 if you do not need them) =0A=
    this.element.makePositioned();=0A=
    this.originalLeft =3D parseFloat(this.element.getStyle('left') || =
'0');=0A=
    this.originalTop  =3D parseFloat(this.element.getStyle('top')  || =
'0');=0A=
    if(this.options.mode =3D=3D 'absolute') {=0A=
      // absolute movement, so we need to calc deltaX and deltaY=0A=
      this.options.x =3D this.options.x - this.originalLeft;=0A=
      this.options.y =3D this.options.y - this.originalTop;=0A=
    }=0A=
  },=0A=
  update: function(position) {=0A=
    this.element.setStyle({=0A=
      left: Math.round(this.options.x  * position + this.originalLeft) + =
'px',=0A=
      top:  Math.round(this.options.y  * position + this.originalTop)  + =
'px'=0A=
    });=0A=
  }=0A=
});=0A=
=0A=
// for backwards compatibility=0A=
Effect.MoveBy =3D function(element, toTop, toLeft) {=0A=
  return new Effect.Move(element, =0A=
    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));=0A=
};=0A=
=0A=
Effect.Scale =3D Class.create();=0A=
Object.extend(Object.extend(Effect.Scale.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function(element, percent) {=0A=
    this.element =3D $(element);=0A=
    if(!this.element) throw(Effect._elementDoesNotExistError);=0A=
    var options =3D Object.extend({=0A=
      scaleX: true,=0A=
      scaleY: true,=0A=
      scaleContent: true,=0A=
      scaleFromCenter: false,=0A=
      scaleMode: 'box',        // 'box' or 'contents' or {} with =
provided values=0A=
      scaleFrom: 100.0,=0A=
      scaleTo:   percent=0A=
    }, arguments[2] || {});=0A=
    this.start(options);=0A=
  },=0A=
  setup: function() {=0A=
    this.restoreAfterFinish =3D this.options.restoreAfterFinish || false;=0A=
    this.elementPositioning =3D this.element.getStyle('position');=0A=
    =0A=
    this.originalStyle =3D {};=0A=
    ['top','left','width','height','fontSize'].each( function(k) {=0A=
      this.originalStyle[k] =3D this.element.style[k];=0A=
    }.bind(this));=0A=
      =0A=
    this.originalTop  =3D this.element.offsetTop;=0A=
    this.originalLeft =3D this.element.offsetLeft;=0A=
    =0A=
    var fontSize =3D this.element.getStyle('font-size') || '100%';=0A=
    ['em','px','%','pt'].each( function(fontSizeType) {=0A=
      if(fontSize.indexOf(fontSizeType)>0) {=0A=
        this.fontSize     =3D parseFloat(fontSize);=0A=
        this.fontSizeType =3D fontSizeType;=0A=
      }=0A=
    }.bind(this));=0A=
    =0A=
    this.factor =3D (this.options.scaleTo - this.options.scaleFrom)/100;=0A=
    =0A=
    this.dims =3D null;=0A=
    if(this.options.scaleMode=3D=3D'box')=0A=
      this.dims =3D [this.element.offsetHeight, =
this.element.offsetWidth];=0A=
    if(/^content/.test(this.options.scaleMode))=0A=
      this.dims =3D [this.element.scrollHeight, =
this.element.scrollWidth];=0A=
    if(!this.dims)=0A=
      this.dims =3D [this.options.scaleMode.originalHeight,=0A=
                   this.options.scaleMode.originalWidth];=0A=
  },=0A=
  update: function(position) {=0A=
    var currentScale =3D (this.options.scaleFrom/100.0) + (this.factor * =
position);=0A=
    if(this.options.scaleContent && this.fontSize)=0A=
      this.element.setStyle({fontSize: this.fontSize * currentScale + =
this.fontSizeType });=0A=
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * =
currentScale);=0A=
  },=0A=
  finish: function(position) {=0A=
    if(this.restoreAfterFinish) =
this.element.setStyle(this.originalStyle);=0A=
  },=0A=
  setDimensions: function(height, width) {=0A=
    var d =3D {};=0A=
    if(this.options.scaleX) d.width =3D Math.round(width) + 'px';=0A=
    if(this.options.scaleY) d.height =3D Math.round(height) + 'px';=0A=
    if(this.options.scaleFromCenter) {=0A=
      var topd  =3D (height - this.dims[0])/2;=0A=
      var leftd =3D (width  - this.dims[1])/2;=0A=
      if(this.elementPositioning =3D=3D 'absolute') {=0A=
        if(this.options.scaleY) d.top =3D this.originalTop-topd + 'px';=0A=
        if(this.options.scaleX) d.left =3D this.originalLeft-leftd + =
'px';=0A=
      } else {=0A=
        if(this.options.scaleY) d.top =3D -topd + 'px';=0A=
        if(this.options.scaleX) d.left =3D -leftd + 'px';=0A=
      }=0A=
    }=0A=
    this.element.setStyle(d);=0A=
  }=0A=
});=0A=
=0A=
Effect.Highlight =3D Class.create();=0A=
Object.extend(Object.extend(Effect.Highlight.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function(element) {=0A=
    this.element =3D $(element);=0A=
    if(!this.element) throw(Effect._elementDoesNotExistError);=0A=
    var options =3D Object.extend({ startcolor: '#ffff99' }, =
arguments[1] || {});=0A=
    this.start(options);=0A=
  },=0A=
  setup: function() {=0A=
    // Prevent executing on elements not in the layout flow=0A=
    if(this.element.getStyle('display')=3D=3D'none') { this.cancel(); =
return; }=0A=
    // Disable background image during the effect=0A=
    this.oldStyle =3D {=0A=
      backgroundImage: this.element.getStyle('background-image') };=0A=
    this.element.setStyle({backgroundImage: 'none'});=0A=
    if(!this.options.endcolor)=0A=
      this.options.endcolor =3D =
this.element.getStyle('background-color').parseColor('#ffffff');=0A=
    if(!this.options.restorecolor)=0A=
      this.options.restorecolor =3D =
this.element.getStyle('background-color');=0A=
    // init color calculations=0A=
    this._base  =3D $R(0,2).map(function(i){ return =
parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));=0A=
    this._delta =3D $R(0,2).map(function(i){ return =
parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] =
}.bind(this));=0A=
  },=0A=
  update: function(position) {=0A=
    this.element.setStyle({backgroundColor: =
$R(0,2).inject('#',function(m,v,i){=0A=
      return =
m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); =
}.bind(this)) });=0A=
  },=0A=
  finish: function() {=0A=
    this.element.setStyle(Object.extend(this.oldStyle, {=0A=
      backgroundColor: this.options.restorecolor=0A=
    }));=0A=
  }=0A=
});=0A=
=0A=
Effect.ScrollTo =3D Class.create();=0A=
Object.extend(Object.extend(Effect.ScrollTo.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function(element) {=0A=
    this.element =3D $(element);=0A=
    this.start(arguments[1] || {});=0A=
  },=0A=
  setup: function() {=0A=
    Position.prepare();=0A=
    var offsets =3D Position.cumulativeOffset(this.element);=0A=
    if(this.options.offset) offsets[1] +=3D this.options.offset;=0A=
    var max =3D window.innerHeight ? =0A=
      window.height - window.innerHeight :=0A=
      document.body.scrollHeight - =0A=
        (document.documentElement.clientHeight ? =0A=
          document.documentElement.clientHeight : =
document.body.clientHeight);=0A=
    this.scrollStart =3D Position.deltaY;=0A=
    this.delta =3D (offsets[1] > max ? max : offsets[1]) - =
this.scrollStart;=0A=
  },=0A=
  update: function(position) {=0A=
    Position.prepare();=0A=
    window.scrollTo(Position.deltaX, =0A=
      this.scrollStart + (position*this.delta));=0A=
  }=0A=
});=0A=
=0A=
/* ------------- combination effects ------------- */=0A=
=0A=
Effect.Fade =3D function(element) {=0A=
  element =3D $(element);=0A=
  var oldOpacity =3D element.getInlineOpacity();=0A=
  var options =3D Object.extend({=0A=
  from: element.getOpacity() || 1.0,=0A=
  to:   0.0,=0A=
  afterFinishInternal: function(effect) { =0A=
    if(effect.options.to!=3D0) return;=0A=
    effect.element.hide().setStyle({opacity: oldOpacity}); =0A=
  }}, arguments[1] || {});=0A=
  return new Effect.Opacity(element,options);=0A=
}=0A=
=0A=
Effect.Appear =3D function(element) {=0A=
  element =3D $(element);=0A=
  var options =3D Object.extend({=0A=
  from: (element.getStyle('display') =3D=3D 'none' ? 0.0 : =
element.getOpacity() || 0.0),=0A=
  to:   1.0,=0A=
  // force Safari to render floated elements properly=0A=
  afterFinishInternal: function(effect) {=0A=
    effect.element.forceRerendering();=0A=
  },=0A=
  beforeSetup: function(effect) {=0A=
    effect.element.setOpacity(effect.options.from).show(); =0A=
  }}, arguments[1] || {});=0A=
  return new Effect.Opacity(element,options);=0A=
}=0A=
=0A=
Effect.Puff =3D function(element) {=0A=
  element =3D $(element);=0A=
  var oldStyle =3D { =0A=
    opacity: element.getInlineOpacity(), =0A=
    position: element.getStyle('position'),=0A=
    top:  element.style.top,=0A=
    left: element.style.left,=0A=
    width: element.style.width,=0A=
    height: element.style.height=0A=
  };=0A=
  return new Effect.Parallel(=0A=
   [ new Effect.Scale(element, 200, =0A=
      { sync: true, scaleFromCenter: true, scaleContent: true, =
restoreAfterFinish: true }), =0A=
     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], =0A=
     Object.extend({ duration: 1.0, =0A=
      beforeSetupInternal: function(effect) {=0A=
        Position.absolutize(effect.effects[0].element)=0A=
      },=0A=
      afterFinishInternal: function(effect) {=0A=
         effect.effects[0].element.hide().setStyle(oldStyle); }=0A=
     }, arguments[1] || {})=0A=
   );=0A=
}=0A=
=0A=
Effect.BlindUp =3D function(element) {=0A=
  element =3D $(element);=0A=
  element.makeClipping();=0A=
  return new Effect.Scale(element, 0,=0A=
    Object.extend({ scaleContent: false, =0A=
      scaleX: false, =0A=
      restoreAfterFinish: true,=0A=
      afterFinishInternal: function(effect) {=0A=
        effect.element.hide().undoClipping();=0A=
      } =0A=
    }, arguments[1] || {})=0A=
  );=0A=
}=0A=
=0A=
Effect.BlindDown =3D function(element) {=0A=
  element =3D $(element);=0A=
  var elementDimensions =3D element.getDimensions();=0A=
  return new Effect.Scale(element, 100, Object.extend({ =0A=
    scaleContent: false, =0A=
    scaleX: false,=0A=
    scaleFrom: 0,=0A=
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: =
elementDimensions.width},=0A=
    restoreAfterFinish: true,=0A=
    afterSetup: function(effect) {=0A=
      effect.element.makeClipping().setStyle({height: '0px'}).show(); =0A=
    },  =0A=
    afterFinishInternal: function(effect) {=0A=
      effect.element.undoClipping();=0A=
    }=0A=
  }, arguments[1] || {}));=0A=
}=0A=
=0A=
Effect.SwitchOff =3D function(element) {=0A=
  element =3D $(element);=0A=
  var oldOpacity =3D element.getInlineOpacity();=0A=
  return new Effect.Appear(element, Object.extend({=0A=
    duration: 0.4,=0A=
    from: 0,=0A=
    transition: Effect.Transitions.flicker,=0A=
    afterFinishInternal: function(effect) {=0A=
      new Effect.Scale(effect.element, 1, { =0A=
        duration: 0.3, scaleFromCenter: true,=0A=
        scaleX: false, scaleContent: false, restoreAfterFinish: true,=0A=
        beforeSetup: function(effect) { =0A=
          effect.element.makePositioned().makeClipping();=0A=
        },=0A=
        afterFinishInternal: function(effect) {=0A=
          =
effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: =
oldOpacity});=0A=
        }=0A=
      })=0A=
    }=0A=
  }, arguments[1] || {}));=0A=
}=0A=
=0A=
Effect.DropOut =3D function(element) {=0A=
  element =3D $(element);=0A=
  var oldStyle =3D {=0A=
    top: element.getStyle('top'),=0A=
    left: element.getStyle('left'),=0A=
    opacity: element.getInlineOpacity() };=0A=
  return new Effect.Parallel(=0A=
    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), =0A=
      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],=0A=
    Object.extend(=0A=
      { duration: 0.5,=0A=
        beforeSetup: function(effect) {=0A=
          effect.effects[0].element.makePositioned(); =0A=
        },=0A=
        afterFinishInternal: function(effect) {=0A=
          =
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);=0A=
        } =0A=
      }, arguments[1] || {}));=0A=
}=0A=
=0A=
Effect.Shake =3D function(element) {=0A=
  element =3D $(element);=0A=
  var oldStyle =3D {=0A=
    top: element.getStyle('top'),=0A=
    left: element.getStyle('left') };=0A=
    return new Effect.Move(element, =0A=
      { x:  20, y: 0, duration: 0.05, afterFinishInternal: =
function(effect) {=0A=
    new Effect.Move(effect.element,=0A=
      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: =
function(effect) {=0A=
    new Effect.Move(effect.element,=0A=
      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: =
function(effect) {=0A=
    new Effect.Move(effect.element,=0A=
      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: =
function(effect) {=0A=
    new Effect.Move(effect.element,=0A=
      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: =
function(effect) {=0A=
    new Effect.Move(effect.element,=0A=
      { x: -20, y: 0, duration: 0.05, afterFinishInternal: =
function(effect) {=0A=
        effect.element.undoPositioned().setStyle(oldStyle);=0A=
  }}) }}) }}) }}) }}) }});=0A=
}=0A=
=0A=
Effect.SlideDown =3D function(element) {=0A=
  element =3D $(element).cleanWhitespace();=0A=
  // SlideDown need to have the content of the element wrapped in a =
container element with fixed height!=0A=
  var oldInnerBottom =3D element.down().getStyle('bottom');=0A=
  var elementDimensions =3D element.getDimensions();=0A=
  return new Effect.Scale(element, 100, Object.extend({ =0A=
    scaleContent: false, =0A=
    scaleX: false, =0A=
    scaleFrom: window.opera ? 0 : 1,=0A=
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: =
elementDimensions.width},=0A=
    restoreAfterFinish: true,=0A=
    afterSetup: function(effect) {=0A=
      effect.element.makePositioned();=0A=
      effect.element.down().makePositioned();=0A=
      if(window.opera) effect.element.setStyle({top: ''});=0A=
      effect.element.makeClipping().setStyle({height: '0px'}).show(); =0A=
    },=0A=
    afterUpdateInternal: function(effect) {=0A=
      effect.element.down().setStyle({bottom:=0A=
        (effect.dims[0] - effect.element.clientHeight) + 'px' }); =0A=
    },=0A=
    afterFinishInternal: function(effect) {=0A=
      effect.element.undoClipping().undoPositioned();=0A=
      effect.element.down().undoPositioned().setStyle({bottom: =
oldInnerBottom}); }=0A=
    }, arguments[1] || {})=0A=
  );=0A=
}=0A=
=0A=
Effect.SlideUp =3D function(element) {=0A=
  element =3D $(element).cleanWhitespace();=0A=
  var oldInnerBottom =3D element.down().getStyle('bottom');=0A=
  return new Effect.Scale(element, window.opera ? 0 : 1,=0A=
   Object.extend({ scaleContent: false, =0A=
    scaleX: false, =0A=
    scaleMode: 'box',=0A=
    scaleFrom: 100,=0A=
    restoreAfterFinish: true,=0A=
    beforeStartInternal: function(effect) {=0A=
      effect.element.makePositioned();=0A=
      effect.element.down().makePositioned();=0A=
      if(window.opera) effect.element.setStyle({top: ''});=0A=
      effect.element.makeClipping().show();=0A=
    },  =0A=
    afterUpdateInternal: function(effect) {=0A=
      effect.element.down().setStyle({bottom:=0A=
        (effect.dims[0] - effect.element.clientHeight) + 'px' });=0A=
    },=0A=
    afterFinishInternal: function(effect) {=0A=
      =
effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: =
oldInnerBottom});=0A=
      effect.element.down().undoPositioned();=0A=
    }=0A=
   }, arguments[1] || {})=0A=
  );=0A=
}=0A=
=0A=
// Bug in opera makes the TD containing this element expand for a =
instance after finish =0A=
Effect.Squish =3D function(element) {=0A=
  return new Effect.Scale(element, window.opera ? 1 : 0, { =0A=
    restoreAfterFinish: true,=0A=
    beforeSetup: function(effect) {=0A=
      effect.element.makeClipping(); =0A=
    },  =0A=
    afterFinishInternal: function(effect) {=0A=
      effect.element.hide().undoClipping(); =0A=
    }=0A=
  });=0A=
}=0A=
=0A=
Effect.Grow =3D function(element) {=0A=
  element =3D $(element);=0A=
  var options =3D Object.extend({=0A=
    direction: 'center',=0A=
    moveTransition: Effect.Transitions.sinoidal,=0A=
    scaleTransition: Effect.Transitions.sinoidal,=0A=
    opacityTransition: Effect.Transitions.full=0A=
  }, arguments[1] || {});=0A=
  var oldStyle =3D {=0A=
    top: element.style.top,=0A=
    left: element.style.left,=0A=
    height: element.style.height,=0A=
    width: element.style.width,=0A=
    opacity: element.getInlineOpacity() };=0A=
=0A=
  var dims =3D element.getDimensions();    =0A=
  var initialMoveX, initialMoveY;=0A=
  var moveX, moveY;=0A=
  =0A=
  switch (options.direction) {=0A=
    case 'top-left':=0A=
      initialMoveX =3D initialMoveY =3D moveX =3D moveY =3D 0; =0A=
      break;=0A=
    case 'top-right':=0A=
      initialMoveX =3D dims.width;=0A=
      initialMoveY =3D moveY =3D 0;=0A=
      moveX =3D -dims.width;=0A=
      break;=0A=
    case 'bottom-left':=0A=
      initialMoveX =3D moveX =3D 0;=0A=
      initialMoveY =3D dims.height;=0A=
      moveY =3D -dims.height;=0A=
      break;=0A=
    case 'bottom-right':=0A=
      initialMoveX =3D dims.width;=0A=
      initialMoveY =3D dims.height;=0A=
      moveX =3D -dims.width;=0A=
      moveY =3D -dims.height;=0A=
      break;=0A=
    case 'center':=0A=
      initialMoveX =3D dims.width / 2;=0A=
      initialMoveY =3D dims.height / 2;=0A=
      moveX =3D -dims.width / 2;=0A=
      moveY =3D -dims.height / 2;=0A=
      break;=0A=
  }=0A=
  =0A=
  return new Effect.Move(element, {=0A=
    x: initialMoveX,=0A=
    y: initialMoveY,=0A=
    duration: 0.01, =0A=
    beforeSetup: function(effect) {=0A=
      effect.element.hide().makeClipping().makePositioned();=0A=
    },=0A=
    afterFinishInternal: function(effect) {=0A=
      new Effect.Parallel(=0A=
        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, =
from: 0.0, transition: options.opacityTransition }),=0A=
          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: =
true, transition: options.moveTransition }),=0A=
          new Effect.Scale(effect.element, 100, {=0A=
            scaleMode: { originalHeight: dims.height, originalWidth: =
dims.width }, =0A=
            sync: true, scaleFrom: window.opera ? 1 : 0, transition: =
options.scaleTransition, restoreAfterFinish: true})=0A=
        ], Object.extend({=0A=
             beforeSetup: function(effect) {=0A=
               effect.effects[0].element.setStyle({height: =
'0px'}).show(); =0A=
             },=0A=
             afterFinishInternal: function(effect) {=0A=
               =
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldSty=
le); =0A=
             }=0A=
           }, options)=0A=
      )=0A=
    }=0A=
  });=0A=
}=0A=
=0A=
Effect.Shrink =3D function(element) {=0A=
  element =3D $(element);=0A=
  var options =3D Object.extend({=0A=
    direction: 'center',=0A=
    moveTransition: Effect.Transitions.sinoidal,=0A=
    scaleTransition: Effect.Transitions.sinoidal,=0A=
    opacityTransition: Effect.Transitions.none=0A=
  }, arguments[1] || {});=0A=
  var oldStyle =3D {=0A=
    top: element.style.top,=0A=
    left: element.style.left,=0A=
    height: element.style.height,=0A=
    width: element.style.width,=0A=
    opacity: element.getInlineOpacity() };=0A=
=0A=
  var dims =3D element.getDimensions();=0A=
  var moveX, moveY;=0A=
  =0A=
  switch (options.direction) {=0A=
    case 'top-left':=0A=
      moveX =3D moveY =3D 0;=0A=
      break;=0A=
    case 'top-right':=0A=
      moveX =3D dims.width;=0A=
      moveY =3D 0;=0A=
      break;=0A=
    case 'bottom-left':=0A=
      moveX =3D 0;=0A=
      moveY =3D dims.height;=0A=
      break;=0A=
    case 'bottom-right':=0A=
      moveX =3D dims.width;=0A=
      moveY =3D dims.height;=0A=
      break;=0A=
    case 'center':  =0A=
      moveX =3D dims.width / 2;=0A=
      moveY =3D dims.height / 2;=0A=
      break;=0A=
  }=0A=
  =0A=
  return new Effect.Parallel(=0A=
    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, =
transition: options.opacityTransition }),=0A=
      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, =
transition: options.scaleTransition, restoreAfterFinish: true}),=0A=
      new Effect.Move(element, { x: moveX, y: moveY, sync: true, =
transition: options.moveTransition })=0A=
    ], Object.extend({            =0A=
         beforeStartInternal: function(effect) {=0A=
           effect.effects[0].element.makePositioned().makeClipping(); =0A=
         },=0A=
         afterFinishInternal: function(effect) {=0A=
           =
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle=
(oldStyle); }=0A=
       }, options)=0A=
  );=0A=
}=0A=
=0A=
Effect.Pulsate =3D function(element) {=0A=
  element =3D $(element);=0A=
  var options    =3D arguments[1] || {};=0A=
  var oldOpacity =3D element.getInlineOpacity();=0A=
  var transition =3D options.transition || Effect.Transitions.sinoidal;=0A=
  var reverser   =3D function(pos){ return =
transition(1-Effect.Transitions.pulse(pos, options.pulses)) };=0A=
  reverser.bind(transition);=0A=
  return new Effect.Opacity(element, =0A=
    Object.extend(Object.extend({  duration: 2.0, from: 0,=0A=
      afterFinishInternal: function(effect) { =
effect.element.setStyle({opacity: oldOpacity}); }=0A=
    }, options), {transition: reverser}));=0A=
}=0A=
=0A=
Effect.Fold =3D function(element) {=0A=
  element =3D $(element);=0A=
  var oldStyle =3D {=0A=
    top: element.style.top,=0A=
    left: element.style.left,=0A=
    width: element.style.width,=0A=
    height: element.style.height };=0A=
  element.makeClipping();=0A=
  return new Effect.Scale(element, 5, Object.extend({   =0A=
    scaleContent: false,=0A=
    scaleX: false,=0A=
    afterFinishInternal: function(effect) {=0A=
    new Effect.Scale(element, 1, { =0A=
      scaleContent: false, =0A=
      scaleY: false,=0A=
      afterFinishInternal: function(effect) {=0A=
        effect.element.hide().undoClipping().setStyle(oldStyle);=0A=
      } });=0A=
  }}, arguments[1] || {}));=0A=
};=0A=
=0A=
Effect.Morph =3D Class.create();=0A=
Object.extend(Object.extend(Effect.Morph.prototype, =
Effect.Base.prototype), {=0A=
  initialize: function(element) {=0A=
    this.element =3D $(element);=0A=
    if(!this.element) throw(Effect._elementDoesNotExistError);=0A=
    var options =3D Object.extend({=0A=
      style: ''=0A=
    }, arguments[1] || {});=0A=
    this.start(options);=0A=
  },=0A=
  setup: function(){=0A=
    function parseColor(color){=0A=
      if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) =
color =3D '#ffffff';=0A=
      color =3D color.parseColor();=0A=
      return $R(0,2).map(function(i){=0A=
        return parseInt( color.slice(i*2+1,i*2+3), 16 ) =0A=
      });=0A=
    }=0A=
    this.transforms =3D =
this.options.style.parseStyle().map(function(property){=0A=
      var originalValue =3D this.element.getStyle(property[0]);=0A=
      return $H({ =0A=
        style: property[0], =0A=
        originalValue: property[1].unit=3D=3D'color' ? =0A=
          parseColor(originalValue) : parseFloat(originalValue || 0), =0A=
        targetValue: property[1].unit=3D=3D'color' ? =0A=
          parseColor(property[1].value) : property[1].value,=0A=
        unit: property[1].unit=0A=
      });=0A=
    }.bind(this)).reject(function(transform){=0A=
      return (=0A=
        (transform.originalValue =3D=3D transform.targetValue) ||=0A=
        (=0A=
          transform.unit !=3D 'color' &&=0A=
          (isNaN(transform.originalValue) || =
isNaN(transform.targetValue))=0A=
        )=0A=
      )=0A=
    });=0A=
  },=0A=
  update: function(position) {=0A=
    var style =3D $H(), value =3D null;=0A=
    this.transforms.each(function(transform){=0A=
      value =3D transform.unit=3D=3D'color' ?=0A=
        $R(0,2).inject('#',function(m,v,i){=0A=
          return m+(Math.round(transform.originalValue[i]+=0A=
            (transform.targetValue[i] - =
transform.originalValue[i])*position)).toColorPart() }) : =0A=
        transform.originalValue + Math.round(=0A=
          ((transform.targetValue - transform.originalValue) * position) =
* 1000)/1000 + transform.unit;=0A=
      style[transform.style] =3D value;=0A=
    });=0A=
    this.element.setStyle(style);=0A=
  }=0A=
});=0A=
=0A=
Effect.Transform =3D Class.create();=0A=
Object.extend(Effect.Transform.prototype, {=0A=
  initialize: function(tracks){=0A=
    this.tracks  =3D [];=0A=
    this.options =3D arguments[1] || {};=0A=
    this.addTracks(tracks);=0A=
  },=0A=
  addTracks: function(tracks){=0A=
    tracks.each(function(track){=0A=
      var data =3D $H(track).values().first();=0A=
      this.tracks.push($H({=0A=
        ids:     $H(track).keys().first(),=0A=
        effect:  Effect.Morph,=0A=
        options: { style: data }=0A=
      }));=0A=
    }.bind(this));=0A=
    return this;=0A=
  },=0A=
  play: function(){=0A=
    return new Effect.Parallel(=0A=
      this.tracks.map(function(track){=0A=
        var elements =3D [$(track.ids) || $$(track.ids)].flatten();=0A=
        return elements.map(function(e){ return new track.effect(e, =
Object.extend({ sync:true }, track.options)) });=0A=
      }).flatten(),=0A=
      this.options=0A=
    );=0A=
  }=0A=
});=0A=
=0A=
Element.CSS_PROPERTIES =3D ['azimuth', 'backgroundAttachment', =
'backgroundColor', 'backgroundImage', =0A=
  'backgroundPosition', 'backgroundRepeat', 'borderBottomColor', =
'borderBottomStyle', =0A=
  'borderBottomWidth', 'borderCollapse', 'borderLeftColor', =
'borderLeftStyle', 'borderLeftWidth',=0A=
  'borderRightColor', 'borderRightStyle', 'borderRightWidth', =
'borderSpacing', 'borderTopColor',=0A=
  'borderTopStyle', 'borderTopWidth', 'bottom', 'captionSide', 'clear', =
'clip', 'color', 'content',=0A=
  'counterIncrement', 'counterReset', 'cssFloat', 'cueAfter', =
'cueBefore', 'cursor', 'direction',=0A=
  'display', 'elevation', 'emptyCells', 'fontFamily', 'fontSize', =
'fontSizeAdjust', 'fontStretch',=0A=
  'fontStyle', 'fontVariant', 'fontWeight', 'height', 'left', =
'letterSpacing', 'lineHeight',=0A=
  'listStyleImage', 'listStylePosition', 'listStyleType', =
'marginBottom', 'marginLeft', 'marginRight',=0A=
  'marginTop', 'markerOffset', 'marks', 'maxHeight', 'maxWidth', =
'minHeight', 'minWidth', 'opacity',=0A=
  'orphans', 'outlineColor', 'outlineOffset', 'outlineStyle', =
'outlineWidth', 'overflowX', 'overflowY',=0A=
  'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop', 'page', =
'pageBreakAfter', 'pageBreakBefore',=0A=
  'pageBreakInside', 'pauseAfter', 'pauseBefore', 'pitch', 'pitchRange', =
'position', 'quotes',=0A=
  'richness', 'right', 'size', 'speakHeader', 'speakNumeral', =
'speakPunctuation', 'speechRate', 'stress',=0A=
  'tableLayout', 'textAlign', 'textDecoration', 'textIndent', =
'textShadow', 'textTransform', 'top',=0A=
  'unicodeBidi', 'verticalAlign', 'visibility', 'voiceFamily', 'volume', =
'whiteSpace', 'widows',=0A=
  'width', 'wordSpacing', 'zIndex'];=0A=
  =0A=
Element.CSS_LENGTH =3D =
/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;=0A=
=0A=
String.prototype.parseStyle =3D function(){=0A=
  var element =3D Element.extend(document.createElement('div'));=0A=
  element.innerHTML =3D '<div style=3D"' + this + '"></div>';=0A=
  var style =3D element.down().style, styleRules =3D $H();=0A=
  =0A=
  Element.CSS_PROPERTIES.each(function(property){=0A=
   if(style[property]) styleRules[property] =3D style[property]; =0A=
  });=0A=
  =0A=
  var result =3D $H();=0A=
  =0A=
  styleRules.each(function(pair){=0A=
    var property =3D pair[0], value =3D pair[1], unit =3D null;=0A=
    =0A=
    if(value.parseColor('#zzzzzz') !=3D '#zzzzzz') {=0A=
      value =3D value.parseColor();=0A=
      unit  =3D 'color';=0A=
    } else if(Element.CSS_LENGTH.test(value)) =0A=
      var components =3D value.match(/^([\+\-]?[0-9\.]+)(.*)$/),=0A=
          value =3D parseFloat(components[1]), unit =3D =
(components.length =3D=3D 3) ? components[2] : null;=0A=
    =0A=
    result[property.underscore().dasherize()] =3D $H({ value:value, =
unit:unit });=0A=
  }.bind(this));=0A=
  =0A=
  return result;=0A=
};=0A=
=0A=
Element.morph =3D function(element, style) {=0A=
  new Effect.Morph(element, Object.extend({ style: style }, arguments[2] =
|| {}));=0A=
  return element;=0A=
};=0A=
=0A=
['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setCont=
entZoom',=0A=
 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( =0A=
  function(f) { Element.Methods[f] =3D Element[f]; }=0A=
);=0A=
=0A=
Element.Methods.visualEffect =3D function(element, effect, options) {=0A=
  s =3D effect.gsub(/_/, '-').camelize();=0A=
  effect_class =3D s.charAt(0).toUpperCase() + s.substring(1);=0A=
  new Effect[effect_class](element, options);=0A=
  return $(element);=0A=
};=0A=
=0A=
Element.addMethods();
------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/dragdrop.js?1209768151

// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, =
http://mir.aculo.us)=0A=
//           (c) 2005, 2006 Sammi Williams =
(http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)=0A=
// =0A=
// script.aculo.us is freely distributable under the terms of an =
MIT-style license.=0A=
// For details, see the script.aculo.us web site: http://script.aculo.us/=0A=
=0A=
if(typeof Effect =3D=3D 'undefined')=0A=
  throw("dragdrop.js requires including script.aculo.us' effects.js =
library");=0A=
=0A=
var Droppables =3D {=0A=
  drops: [],=0A=
=0A=
  remove: function(element) {=0A=
    this.drops =3D this.drops.reject(function(d) { return =
d.element=3D=3D$(element) });=0A=
  },=0A=
=0A=
  add: function(element) {=0A=
    element =3D $(element);=0A=
    var options =3D Object.extend({=0A=
      greedy:     true,=0A=
      hoverclass: null,=0A=
      tree:       false=0A=
    }, arguments[1] || {});=0A=
=0A=
    // cache containers=0A=
    if(options.containment) {=0A=
      options._containers =3D [];=0A=
      var containment =3D options.containment;=0A=
      if((typeof containment =3D=3D 'object') && =0A=
        (containment.constructor =3D=3D Array)) {=0A=
        containment.each( function(c) { options._containers.push($(c)) =
});=0A=
      } else {=0A=
        options._containers.push($(containment));=0A=
      }=0A=
    }=0A=
    =0A=
    if(options.accept) options.accept =3D [options.accept].flatten();=0A=
=0A=
    Element.makePositioned(element); // fix IE=0A=
    options.element =3D element;=0A=
=0A=
    this.drops.push(options);=0A=
  },=0A=
  =0A=
  findDeepestChild: function(drops) {=0A=
    deepest =3D drops[0];=0A=
      =0A=
    for (i =3D 1; i < drops.length; ++i)=0A=
      if (Element.isParent(drops[i].element, deepest.element))=0A=
        deepest =3D drops[i];=0A=
    =0A=
    return deepest;=0A=
  },=0A=
=0A=
  isContained: function(element, drop) {=0A=
    var containmentNode;=0A=
    if(drop.tree) {=0A=
      containmentNode =3D element.treeNode; =0A=
    } else {=0A=
      containmentNode =3D element.parentNode;=0A=
    }=0A=
    return drop._containers.detect(function(c) { return containmentNode =
=3D=3D c });=0A=
  },=0A=
  =0A=
  isAffected: function(point, element, drop) {=0A=
    return (=0A=
      (drop.element!=3Delement) &&=0A=
      ((!drop._containers) ||=0A=
        this.isContained(element, drop)) &&=0A=
      ((!drop.accept) ||=0A=
        (Element.classNames(element).detect( =0A=
          function(v) { return drop.accept.include(v) } ) )) &&=0A=
      Position.within(drop.element, point[0], point[1]) );=0A=
  },=0A=
=0A=
  deactivate: function(drop) {=0A=
    if(drop.hoverclass)=0A=
      Element.removeClassName(drop.element, drop.hoverclass);=0A=
    this.last_active =3D null;=0A=
  },=0A=
=0A=
  activate: function(drop) {=0A=
    if(drop.hoverclass)=0A=
      Element.addClassName(drop.element, drop.hoverclass);=0A=
    this.last_active =3D drop;=0A=
  },=0A=
=0A=
  show: function(point, element) {=0A=
    if(!this.drops.length) return;=0A=
    var affected =3D [];=0A=
    =0A=
    if(this.last_active) this.deactivate(this.last_active);=0A=
    this.drops.each( function(drop) {=0A=
      if(Droppables.isAffected(point, element, drop))=0A=
        affected.push(drop);=0A=
    });=0A=
        =0A=
    if(affected.length>0) {=0A=
      drop =3D Droppables.findDeepestChild(affected);=0A=
      Position.within(drop.element, point[0], point[1]);=0A=
      if(drop.onHover)=0A=
        drop.onHover(element, drop.element, =
Position.overlap(drop.overlap, drop.element));=0A=
      =0A=
      Droppables.activate(drop);=0A=
    }=0A=
  },=0A=
=0A=
  fire: function(event, element) {=0A=
    if(!this.last_active) return;=0A=
    Position.prepare();=0A=
=0A=
    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], =
element, this.last_active))=0A=
      if (this.last_active.onDrop) =0A=
        this.last_active.onDrop(element, this.last_active.element, =
event);=0A=
  },=0A=
=0A=
  reset: function() {=0A=
    if(this.last_active)=0A=
      this.deactivate(this.last_active);=0A=
  }=0A=
}=0A=
=0A=
var Draggables =3D {=0A=
  drags: [],=0A=
  observers: [],=0A=
  =0A=
  register: function(draggable) {=0A=
    if(this.drags.length =3D=3D 0) {=0A=
      this.eventMouseUp   =3D this.endDrag.bindAsEventListener(this);=0A=
      this.eventMouseMove =3D this.updateDrag.bindAsEventListener(this);=0A=
      this.eventKeypress  =3D this.keyPress.bindAsEventListener(this);=0A=
      =0A=
      Event.observe(document, "mouseup", this.eventMouseUp);=0A=
      Event.observe(document, "mousemove", this.eventMouseMove);=0A=
      Event.observe(document, "keypress", this.eventKeypress);=0A=
    }=0A=
    this.drags.push(draggable);=0A=
  },=0A=
  =0A=
  unregister: function(draggable) {=0A=
    this.drags =3D this.drags.reject(function(d) { return =
d=3D=3Ddraggable });=0A=
    if(this.drags.length =3D=3D 0) {=0A=
      Event.stopObserving(document, "mouseup", this.eventMouseUp);=0A=
      Event.stopObserving(document, "mousemove", this.eventMouseMove);=0A=
      Event.stopObserving(document, "keypress", this.eventKeypress);=0A=
    }=0A=
  },=0A=
  =0A=
  activate: function(draggable) {=0A=
    if(draggable.options.delay) { =0A=
      this._timeout =3D setTimeout(function() { =0A=
        Draggables._timeout =3D null; =0A=
        window.focus(); =0A=
        Draggables.activeDraggable =3D draggable; =0A=
      }.bind(this), draggable.options.delay); =0A=
    } else {=0A=
      window.focus(); // allows keypress events if window isn't =
currently focused, fails for Safari=0A=
      this.activeDraggable =3D draggable;=0A=
    }=0A=
  },=0A=
  =0A=
  deactivate: function() {=0A=
    this.activeDraggable =3D null;=0A=
  },=0A=
  =0A=
  updateDrag: function(event) {=0A=
    if(!this.activeDraggable) return;=0A=
    var pointer =3D [Event.pointerX(event), Event.pointerY(event)];=0A=
    // Mozilla-based browsers fire successive mousemove events with=0A=
    // the same coordinates, prevent needless redrawing (moz bug?)=0A=
    if(this._lastPointer && (this._lastPointer.inspect() =3D=3D =
pointer.inspect())) return;=0A=
    this._lastPointer =3D pointer;=0A=
    =0A=
    this.activeDraggable.updateDrag(event, pointer);=0A=
  },=0A=
  =0A=
  endDrag: function(event) {=0A=
    if(this._timeout) { =0A=
      clearTimeout(this._timeout); =0A=
      this._timeout =3D null; =0A=
    }=0A=
    if(!this.activeDraggable) return;=0A=
    this._lastPointer =3D null;=0A=
    this.activeDraggable.endDrag(event);=0A=
    this.activeDraggable =3D null;=0A=
  },=0A=
  =0A=
  keyPress: function(event) {=0A=
    if(this.activeDraggable)=0A=
      this.activeDraggable.keyPress(event);=0A=
  },=0A=
  =0A=
  addObserver: function(observer) {=0A=
    this.observers.push(observer);=0A=
    this._cacheObserverCallbacks();=0A=
  },=0A=
  =0A=
  removeObserver: function(element) {  // element instead of observer =
fixes mem leaks=0A=
    this.observers =3D this.observers.reject( function(o) { return =
o.element=3D=3Delement });=0A=
    this._cacheObserverCallbacks();=0A=
  },=0A=
  =0A=
  notify: function(eventName, draggable, event) {  // 'onStart', =
'onEnd', 'onDrag'=0A=
    if(this[eventName+'Count'] > 0)=0A=
      this.observers.each( function(o) {=0A=
        if(o[eventName]) o[eventName](eventName, draggable, event);=0A=
      });=0A=
    if(draggable.options[eventName]) =
draggable.options[eventName](draggable, event);=0A=
  },=0A=
  =0A=
  _cacheObserverCallbacks: function() {=0A=
    ['onStart','onEnd','onDrag'].each( function(eventName) {=0A=
      Draggables[eventName+'Count'] =3D Draggables.observers.select(=0A=
        function(o) { return o[eventName]; }=0A=
      ).length;=0A=
    });=0A=
  }=0A=
}=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
var Draggable =3D Class.create();=0A=
Draggable._dragging    =3D {};=0A=
=0A=
Draggable.prototype =3D {=0A=
  initialize: function(element) {=0A=
    var defaults =3D {=0A=
      handle: false,=0A=
      reverteffect: function(element, top_offset, left_offset) {=0A=
        var dur =3D =
Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;=0A=
        new Effect.Move(element, { x: -left_offset, y: -top_offset, =
duration: dur,=0A=
          queue: {scope:'_draggable', position:'end'}=0A=
        });=0A=
      },=0A=
      endeffect: function(element) {=0A=
        var toOpacity =3D typeof element._opacity =3D=3D 'number' ? =
element._opacity : 1.0;=0A=
        new Effect.Opacity(element, {duration:0.2, from:0.7, =
to:toOpacity, =0A=
          queue: {scope:'_draggable', position:'end'},=0A=
          afterFinish: function(){ =0A=
            Draggable._dragging[element] =3D false =0A=
          }=0A=
        }); =0A=
      },=0A=
      zindex: 1000,=0A=
      revert: false,=0A=
      scroll: false,=0A=
      scrollSensitivity: 20,=0A=
      scrollSpeed: 15,=0A=
      snap: false,  // false, or xy or [x,y] or function(x,y){ return =
[x,y] }=0A=
      delay: 0=0A=
    };=0A=
    =0A=
    if(!arguments[1] || typeof arguments[1].endeffect =3D=3D 'undefined')=0A=
      Object.extend(defaults, {=0A=
        starteffect: function(element) {=0A=
          element._opacity =3D Element.getOpacity(element);=0A=
          Draggable._dragging[element] =3D true;=0A=
          new Effect.Opacity(element, {duration:0.2, =
from:element._opacity, to:0.7}); =0A=
        }=0A=
      });=0A=
    =0A=
    var options =3D Object.extend(defaults, arguments[1] || {});=0A=
=0A=
    this.element =3D $(element);=0A=
    =0A=
    if(options.handle && (typeof options.handle =3D=3D 'string'))=0A=
      this.handle =3D this.element.down('.'+options.handle, 0);=0A=
    =0A=
    if(!this.handle) this.handle =3D $(options.handle);=0A=
    if(!this.handle) this.handle =3D this.element;=0A=
    =0A=
    if(options.scroll && !options.scroll.scrollTo && =
!options.scroll.outerHTML) {=0A=
      options.scroll =3D $(options.scroll);=0A=
      this._isScrollChild =3D Element.childOf(this.element, =
options.scroll);=0A=
    }=0A=
=0A=
    Element.makePositioned(this.element); // fix IE    =0A=
=0A=
    this.delta    =3D this.currentDelta();=0A=
    this.options  =3D options;=0A=
    this.dragging =3D false;   =0A=
=0A=
    this.eventMouseDown =3D this.initDrag.bindAsEventListener(this);=0A=
    Event.observe(this.handle, "mousedown", this.eventMouseDown);=0A=
    =0A=
    Draggables.register(this);=0A=
  },=0A=
  =0A=
  destroy: function() {=0A=
    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);=0A=
    Draggables.unregister(this);=0A=
  },=0A=
  =0A=
  currentDelta: function() {=0A=
    return([=0A=
      parseInt(Element.getStyle(this.element,'left') || '0'),=0A=
      parseInt(Element.getStyle(this.element,'top') || '0')]);=0A=
  },=0A=
  =0A=
  initDrag: function(event) {=0A=
    if(typeof Draggable._dragging[this.element] !=3D 'undefined' &&=0A=
      Draggable._dragging[this.element]) return;=0A=
    if(Event.isLeftClick(event)) {    =0A=
      // abort on form elements, fixes a Firefox issue=0A=
      var src =3D Event.element(event);=0A=
      if(src.tagName && (=0A=
        src.tagName=3D=3D'INPUT' ||=0A=
        src.tagName=3D=3D'SELECT' ||=0A=
        src.tagName=3D=3D'OPTION' ||=0A=
        src.tagName=3D=3D'BUTTON' ||=0A=
        src.tagName=3D=3D'TEXTAREA')) return;=0A=
        =0A=
      var pointer =3D [Event.pointerX(event), Event.pointerY(event)];=0A=
      var pos     =3D Position.cumulativeOffset(this.element);=0A=
      this.offset =3D [0,1].map( function(i) { return (pointer[i] - =
pos[i]) });=0A=
      =0A=
      Draggables.activate(this);=0A=
      Event.stop(event);=0A=
    }=0A=
  },=0A=
  =0A=
  startDrag: function(event) {=0A=
    this.dragging =3D true;=0A=
    =0A=
    if(this.options.zindex) {=0A=
      this.originalZ =3D =
parseInt(Element.getStyle(this.element,'z-index') || 0);=0A=
      this.element.style.zIndex =3D this.options.zindex;=0A=
    }=0A=
    =0A=
    if(this.options.ghosting) {=0A=
      this._clone =3D this.element.cloneNode(true);=0A=
      Position.absolutize(this.element);=0A=
      this.element.parentNode.insertBefore(this._clone, this.element);=0A=
    }=0A=
    =0A=
    if(this.options.scroll) {=0A=
      if (this.options.scroll =3D=3D window) {=0A=
        var where =3D this._getWindowScroll(this.options.scroll);=0A=
        this.originalScrollLeft =3D where.left;=0A=
        this.originalScrollTop =3D where.top;=0A=
      } else {=0A=
        this.originalScrollLeft =3D this.options.scroll.scrollLeft;=0A=
        this.originalScrollTop =3D this.options.scroll.scrollTop;=0A=
      }=0A=
    }=0A=
    =0A=
    Draggables.notify('onStart', this, event);=0A=
        =0A=
    if(this.options.starteffect) this.options.starteffect(this.element);=0A=
  },=0A=
  =0A=
  updateDrag: function(event, pointer) {=0A=
    if(!this.dragging) this.startDrag(event);=0A=
    Position.prepare();=0A=
    Droppables.show(pointer, this.element);=0A=
    Draggables.notify('onDrag', this, event);=0A=
    =0A=
    this.draw(pointer);=0A=
    if(this.options.change) this.options.change(this);=0A=
    =0A=
    if(this.options.scroll) {=0A=
      this.stopScrolling();=0A=
      =0A=
      var p;=0A=
      if (this.options.scroll =3D=3D window) {=0A=
        with(this._getWindowScroll(this.options.scroll)) { p =3D [ left, =
top, left+width, top+height ]; }=0A=
      } else {=0A=
        p =3D Position.page(this.options.scroll);=0A=
        p[0] +=3D this.options.scroll.scrollLeft + Position.deltaX;=0A=
        p[1] +=3D this.options.scroll.scrollTop + Position.deltaY;=0A=
        p.push(p[0]+this.options.scroll.offsetWidth);=0A=
        p.push(p[1]+this.options.scroll.offsetHeight);=0A=
      }=0A=
      var speed =3D [0,0];=0A=
      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] =
=3D pointer[0]-(p[0]+this.options.scrollSensitivity);=0A=
      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] =
=3D pointer[1]-(p[1]+this.options.scrollSensitivity);=0A=
      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] =
=3D pointer[0]-(p[2]-this.options.scrollSensitivity);=0A=
      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] =
=3D pointer[1]-(p[3]-this.options.scrollSensitivity);=0A=
      this.startScrolling(speed);=0A=
    }=0A=
    =0A=
    // fix AppleWebKit rendering=0A=
    if(navigator.appVersion.indexOf('AppleWebKit')>0) =
window.scrollBy(0,0);=0A=
    =0A=
    Event.stop(event);=0A=
  },=0A=
  =0A=
  finishDrag: function(event, success) {=0A=
    this.dragging =3D false;=0A=
=0A=
    if(this.options.ghosting) {=0A=
      Position.relativize(this.element);=0A=
      Element.remove(this._clone);=0A=
      this._clone =3D null;=0A=
    }=0A=
=0A=
    if(success) Droppables.fire(event, this.element);=0A=
    Draggables.notify('onEnd', this, event);=0A=
=0A=
    var revert =3D this.options.revert;=0A=
    if(revert && typeof revert =3D=3D 'function') revert =3D =
revert(this.element);=0A=
    =0A=
    var d =3D this.currentDelta();=0A=
    if(revert && this.options.reverteffect) {=0A=
      this.options.reverteffect(this.element, =0A=
        d[1]-this.delta[1], d[0]-this.delta[0]);=0A=
    } else {=0A=
      this.delta =3D d;=0A=
    }=0A=
=0A=
    if(this.options.zindex)=0A=
      this.element.style.zIndex =3D this.originalZ;=0A=
=0A=
    if(this.options.endeffect) =0A=
      this.options.endeffect(this.element);=0A=
      =0A=
    Draggables.deactivate(this);=0A=
    Droppables.reset();=0A=
  },=0A=
  =0A=
  keyPress: function(event) {=0A=
    if(event.keyCode!=3DEvent.KEY_ESC) return;=0A=
    this.finishDrag(event, false);=0A=
    Event.stop(event);=0A=
  },=0A=
  =0A=
  endDrag: function(event) {=0A=
    if(!this.dragging) return;=0A=
    this.stopScrolling();=0A=
    this.finishDrag(event, true);=0A=
    Event.stop(event);=0A=
  },=0A=
  =0A=
  draw: function(point) {=0A=
    var pos =3D Position.cumulativeOffset(this.element);=0A=
    if(this.options.ghosting) {=0A=
      var r   =3D Position.realOffset(this.element);=0A=
      pos[0] +=3D r[0] - Position.deltaX; pos[1] +=3D r[1] - =
Position.deltaY;=0A=
    }=0A=
    =0A=
    var d =3D this.currentDelta();=0A=
    pos[0] -=3D d[0]; pos[1] -=3D d[1];=0A=
    =0A=
    if(this.options.scroll && (this.options.scroll !=3D window && =
this._isScrollChild)) {=0A=
      pos[0] -=3D this.options.scroll.scrollLeft-this.originalScrollLeft;=0A=
      pos[1] -=3D this.options.scroll.scrollTop-this.originalScrollTop;=0A=
    }=0A=
    =0A=
    var p =3D [0,1].map(function(i){ =0A=
      return (point[i]-pos[i]-this.offset[i]) =0A=
    }.bind(this));=0A=
    =0A=
    if(this.options.snap) {=0A=
      if(typeof this.options.snap =3D=3D 'function') {=0A=
        p =3D this.options.snap(p[0],p[1],this);=0A=
      } else {=0A=
      if(this.options.snap instanceof Array) {=0A=
        p =3D p.map( function(v, i) {=0A=
          return Math.round(v/this.options.snap[i])*this.options.snap[i] =
}.bind(this))=0A=
      } else {=0A=
        p =3D p.map( function(v) {=0A=
          return Math.round(v/this.options.snap)*this.options.snap =
}.bind(this))=0A=
      }=0A=
    }}=0A=
    =0A=
    var style =3D this.element.style;=0A=
    if((!this.options.constraint) || =
(this.options.constraint=3D=3D'horizontal'))=0A=
      style.left =3D p[0] + "px";=0A=
    if((!this.options.constraint) || =
(this.options.constraint=3D=3D'vertical'))=0A=
      style.top  =3D p[1] + "px";=0A=
    =0A=
    if(style.visibility=3D=3D"hidden") style.visibility =3D ""; // fix =
gecko rendering=0A=
  },=0A=
  =0A=
  stopScrolling: function() {=0A=
    if(this.scrollInterval) {=0A=
      clearInterval(this.scrollInterval);=0A=
      this.scrollInterval =3D null;=0A=
      Draggables._lastScrollPointer =3D null;=0A=
    }=0A=
  },=0A=
  =0A=
  startScrolling: function(speed) {=0A=
    if(!(speed[0] || speed[1])) return;=0A=
    this.scrollSpeed =3D =
[speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];=0A=
    this.lastScrolled =3D new Date();=0A=
    this.scrollInterval =3D setInterval(this.scroll.bind(this), 10);=0A=
  },=0A=
  =0A=
  scroll: function() {=0A=
    var current =3D new Date();=0A=
    var delta =3D current - this.lastScrolled;=0A=
    this.lastScrolled =3D current;=0A=
    if(this.options.scroll =3D=3D window) {=0A=
      with (this._getWindowScroll(this.options.scroll)) {=0A=
        if (this.scrollSpeed[0] || this.scrollSpeed[1]) {=0A=
          var d =3D delta / 1000;=0A=
          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], =
top + d*this.scrollSpeed[1] );=0A=
        }=0A=
      }=0A=
    } else {=0A=
      this.options.scroll.scrollLeft +=3D this.scrollSpeed[0] * delta / =
1000;=0A=
      this.options.scroll.scrollTop  +=3D this.scrollSpeed[1] * delta / =
1000;=0A=
    }=0A=
    =0A=
    Position.prepare();=0A=
    Droppables.show(Draggables._lastPointer, this.element);=0A=
    Draggables.notify('onDrag', this);=0A=
    if (this._isScrollChild) {=0A=
      Draggables._lastScrollPointer =3D Draggables._lastScrollPointer || =
$A(Draggables._lastPointer);=0A=
      Draggables._lastScrollPointer[0] +=3D this.scrollSpeed[0] * delta =
/ 1000;=0A=
      Draggables._lastScrollPointer[1] +=3D this.scrollSpeed[1] * delta =
/ 1000;=0A=
      if (Draggables._lastScrollPointer[0] < 0)=0A=
        Draggables._lastScrollPointer[0] =3D 0;=0A=
      if (Draggables._lastScrollPointer[1] < 0)=0A=
        Draggables._lastScrollPointer[1] =3D 0;=0A=
      this.draw(Draggables._lastScrollPointer);=0A=
    }=0A=
    =0A=
    if(this.options.change) this.options.change(this);=0A=
  },=0A=
  =0A=
  _getWindowScroll: function(w) {=0A=
    var T, L, W, H;=0A=
    with (w.document) {=0A=
      if (w.document.documentElement && documentElement.scrollTop) {=0A=
        T =3D documentElement.scrollTop;=0A=
        L =3D documentElement.scrollLeft;=0A=
      } else if (w.document.body) {=0A=
        T =3D body.scrollTop;=0A=
        L =3D body.scrollLeft;=0A=
      }=0A=
      if (w.innerWidth) {=0A=
        W =3D w.innerWidth;=0A=
        H =3D w.innerHeight;=0A=
      } else if (w.document.documentElement && =
documentElement.clientWidth) {=0A=
        W =3D documentElement.clientWidth;=0A=
        H =3D documentElement.clientHeight;=0A=
      } else {=0A=
        W =3D body.offsetWidth;=0A=
        H =3D body.offsetHeight=0A=
      }=0A=
    }=0A=
    return { top: T, left: L, width: W, height: H };=0A=
  }=0A=
}=0A=
=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
var SortableObserver =3D Class.create();=0A=
SortableObserver.prototype =3D {=0A=
  initialize: function(element, observer) {=0A=
    this.element   =3D $(element);=0A=
    this.observer  =3D observer;=0A=
    this.lastValue =3D Sortable.serialize(this.element);=0A=
  },=0A=
  =0A=
  onStart: function() {=0A=
    this.lastValue =3D Sortable.serialize(this.element);=0A=
  },=0A=
  =0A=
  onEnd: function() {=0A=
    Sortable.unmark();=0A=
    if(this.lastValue !=3D Sortable.serialize(this.element))=0A=
      this.observer(this.element)=0A=
  }=0A=
}=0A=
=0A=
var Sortable =3D {=0A=
  SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,=0A=
  =0A=
  sortables: {},=0A=
  =0A=
  _findRootElement: function(element) {=0A=
    while (element.tagName !=3D "BODY") {  =0A=
      if(element.id && Sortable.sortables[element.id]) return element;=0A=
      element =3D element.parentNode;=0A=
    }=0A=
  },=0A=
=0A=
  options: function(element) {=0A=
    element =3D Sortable._findRootElement($(element));=0A=
    if(!element) return;=0A=
    return Sortable.sortables[element.id];=0A=
  },=0A=
  =0A=
  destroy: function(element){=0A=
    var s =3D Sortable.options(element);=0A=
    =0A=
    if(s) {=0A=
      Draggables.removeObserver(s.element);=0A=
      s.droppables.each(function(d){ Droppables.remove(d) });=0A=
      s.draggables.invoke('destroy');=0A=
      =0A=
      delete Sortable.sortables[s.element.id];=0A=
    }=0A=
  },=0A=
=0A=
  create: function(element) {=0A=
    element =3D $(element);=0A=
    var options =3D Object.extend({ =0A=
      element:     element,=0A=
      tag:         'li',       // assumes li children, override with =
tag: 'tagname'=0A=
      dropOnEmpty: false,=0A=
      tree:        false,=0A=
      treeTag:     'ul',=0A=
      overlap:     'vertical', // one of 'vertical', 'horizontal'=0A=
      constraint:  'vertical', // one of 'vertical', 'horizontal', false=0A=
      containment: element,    // also takes array of elements (or =
id's); or false=0A=
      handle:      false,      // or a CSS class=0A=
      only:        false,=0A=
      delay:       0,=0A=
      hoverclass:  null,=0A=
      ghosting:    false,=0A=
      scroll:      false,=0A=
      scrollSensitivity: 20,=0A=
      scrollSpeed: 15,=0A=
      format:      this.SERIALIZE_RULE,=0A=
      onChange:    Prototype.emptyFunction,=0A=
      onUpdate:    Prototype.emptyFunction=0A=
    }, arguments[1] || {});=0A=
=0A=
    // clear any old sortable with same element=0A=
    this.destroy(element);=0A=
=0A=
    // build options for the draggables=0A=
    var options_for_draggable =3D {=0A=
      revert:      true,=0A=
      scroll:      options.scroll,=0A=
      scrollSpeed: options.scrollSpeed,=0A=
      scrollSensitivity: options.scrollSensitivity,=0A=
      delay:       options.delay,=0A=
      ghosting:    options.ghosting,=0A=
      constraint:  options.constraint,=0A=
      handle:      options.handle };=0A=
=0A=
    if(options.starteffect)=0A=
      options_for_draggable.starteffect =3D options.starteffect;=0A=
=0A=
    if(options.reverteffect)=0A=
      options_for_draggable.reverteffect =3D options.reverteffect;=0A=
    else=0A=
      if(options.ghosting) options_for_draggable.reverteffect =3D =
function(element) {=0A=
        element.style.top  =3D 0;=0A=
        element.style.left =3D 0;=0A=
      };=0A=
=0A=
    if(options.endeffect)=0A=
      options_for_draggable.endeffect =3D options.endeffect;=0A=
=0A=
    if(options.zindex)=0A=
      options_for_draggable.zindex =3D options.zindex;=0A=
=0A=
    // build options for the droppables  =0A=
    var options_for_droppable =3D {=0A=
      overlap:     options.overlap,=0A=
      containment: options.containment,=0A=
      tree:        options.tree,=0A=
      hoverclass:  options.hoverclass,=0A=
      onHover:     Sortable.onHover=0A=
    }=0A=
    =0A=
    var options_for_tree =3D {=0A=
      onHover:      Sortable.onEmptyHover,=0A=
      overlap:      options.overlap,=0A=
      containment:  options.containment,=0A=
      hoverclass:   options.hoverclass=0A=
    }=0A=
=0A=
    // fix for gecko engine=0A=
    Element.cleanWhitespace(element); =0A=
=0A=
    options.draggables =3D [];=0A=
    options.droppables =3D [];=0A=
=0A=
    // drop on empty handling=0A=
    if(options.dropOnEmpty || options.tree) {=0A=
      Droppables.add(element, options_for_tree);=0A=
      options.droppables.push(element);=0A=
    }=0A=
=0A=
    (this.findElements(element, options) || []).each( function(e) {=0A=
      // handles are per-draggable=0A=
      var handle =3D options.handle ? =0A=
        $(e).down('.'+options.handle,0) : e;    =0A=
      options.draggables.push(=0A=
        new Draggable(e, Object.extend(options_for_draggable, { handle: =
handle })));=0A=
      Droppables.add(e, options_for_droppable);=0A=
      if(options.tree) e.treeNode =3D element;=0A=
      options.droppables.push(e);      =0A=
    });=0A=
    =0A=
    if(options.tree) {=0A=
      (Sortable.findTreeElements(element, options) || []).each( =
function(e) {=0A=
        Droppables.add(e, options_for_tree);=0A=
        e.treeNode =3D element;=0A=
        options.droppables.push(e);=0A=
      });=0A=
    }=0A=
=0A=
    // keep reference=0A=
    this.sortables[element.id] =3D options;=0A=
=0A=
    // for onupdate=0A=
    Draggables.addObserver(new SortableObserver(element, =
options.onUpdate));=0A=
=0A=
  },=0A=
=0A=
  // return all suitable-for-sortable elements in a guaranteed order=0A=
  findElements: function(element, options) {=0A=
    return Element.findChildren(=0A=
      element, options.only, options.tree ? true : false, options.tag);=0A=
  },=0A=
  =0A=
  findTreeElements: function(element, options) {=0A=
    return Element.findChildren(=0A=
      element, options.only, options.tree ? true : false, =
options.treeTag);=0A=
  },=0A=
=0A=
  onHover: function(element, dropon, overlap) {=0A=
    if(Element.isParent(dropon, element)) return;=0A=
=0A=
    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {=0A=
      return;=0A=
    } else if(overlap>0.5) {=0A=
      Sortable.mark(dropon, 'before');=0A=
      if(dropon.previousSibling !=3D element) {=0A=
        var oldParentNode =3D element.parentNode;=0A=
        element.style.visibility =3D "hidden"; // fix gecko rendering=0A=
        dropon.parentNode.insertBefore(element, dropon);=0A=
        if(dropon.parentNode!=3DoldParentNode) =0A=
          Sortable.options(oldParentNode).onChange(element);=0A=
        Sortable.options(dropon.parentNode).onChange(element);=0A=
      }=0A=
    } else {=0A=
      Sortable.mark(dropon, 'after');=0A=
      var nextElement =3D dropon.nextSibling || null;=0A=
      if(nextElement !=3D element) {=0A=
        var oldParentNode =3D element.parentNode;=0A=
        element.style.visibility =3D "hidden"; // fix gecko rendering=0A=
        dropon.parentNode.insertBefore(element, nextElement);=0A=
        if(dropon.parentNode!=3DoldParentNode) =0A=
          Sortable.options(oldParentNode).onChange(element);=0A=
        Sortable.options(dropon.parentNode).onChange(element);=0A=
      }=0A=
    }=0A=
  },=0A=
  =0A=
  onEmptyHover: function(element, dropon, overlap) {=0A=
    var oldParentNode =3D element.parentNode;=0A=
    var droponOptions =3D Sortable.options(dropon);=0A=
        =0A=
    if(!Element.isParent(dropon, element)) {=0A=
      var index;=0A=
      =0A=
      var children =3D Sortable.findElements(dropon, {tag: =
droponOptions.tag, only: droponOptions.only});=0A=
      var child =3D null;=0A=
            =0A=
      if(children) {=0A=
        var offset =3D Element.offsetSize(dropon, droponOptions.overlap) =
* (1.0 - overlap);=0A=
        =0A=
        for (index =3D 0; index < children.length; index +=3D 1) {=0A=
          if (offset - Element.offsetSize (children[index], =
droponOptions.overlap) >=3D 0) {=0A=
            offset -=3D Element.offsetSize (children[index], =
droponOptions.overlap);=0A=
          } else if (offset - (Element.offsetSize (children[index], =
droponOptions.overlap) / 2) >=3D 0) {=0A=
            child =3D index + 1 < children.length ? children[index + 1] =
: null;=0A=
            break;=0A=
          } else {=0A=
            child =3D children[index];=0A=
            break;=0A=
          }=0A=
        }=0A=
      }=0A=
      =0A=
      dropon.insertBefore(element, child);=0A=
      =0A=
      Sortable.options(oldParentNode).onChange(element);=0A=
      droponOptions.onChange(element);=0A=
    }=0A=
  },=0A=
=0A=
  unmark: function() {=0A=
    if(Sortable._marker) Sortable._marker.hide();=0A=
  },=0A=
=0A=
  mark: function(dropon, position) {=0A=
    // mark on ghosting only=0A=
    var sortable =3D Sortable.options(dropon.parentNode);=0A=
    if(sortable && !sortable.ghosting) return; =0A=
=0A=
    if(!Sortable._marker) {=0A=
      Sortable._marker =3D =0A=
        ($('dropmarker') || =
Element.extend(document.createElement('DIV'))).=0A=
          =
hide().addClassName('dropmarker').setStyle({position:'absolute'});=0A=
      =
document.getElementsByTagName("body").item(0).appendChild(Sortable._marke=
r);=0A=
    }    =0A=
    var offsets =3D Position.cumulativeOffset(dropon);=0A=
    Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + =
'px'});=0A=
    =0A=
    if(position=3D=3D'after')=0A=
      if(sortable.overlap =3D=3D 'horizontal') =0A=
        Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) =
+ 'px'});=0A=
      else=0A=
        Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) =
+ 'px'});=0A=
    =0A=
    Sortable._marker.show();=0A=
  },=0A=
  =0A=
  _tree: function(element, options, parent) {=0A=
    var children =3D Sortable.findElements(element, options) || [];=0A=
  =0A=
    for (var i =3D 0; i < children.length; ++i) {=0A=
      var match =3D children[i].id.match(options.format);=0A=
=0A=
      if (!match) continue;=0A=
      =0A=
      var child =3D {=0A=
        id: encodeURIComponent(match ? match[1] : null),=0A=
        element: element,=0A=
        parent: parent,=0A=
        children: [],=0A=
        position: parent.children.length,=0A=
        container: $(children[i]).down(options.treeTag)=0A=
      }=0A=
      =0A=
      /* Get the element containing the children and recurse over it */=0A=
      if (child.container)=0A=
        this._tree(child.container, options, child)=0A=
      =0A=
      parent.children.push (child);=0A=
    }=0A=
=0A=
    return parent; =0A=
  },=0A=
=0A=
  tree: function(element) {=0A=
    element =3D $(element);=0A=
    var sortableOptions =3D this.options(element);=0A=
    var options =3D Object.extend({=0A=
      tag: sortableOptions.tag,=0A=
      treeTag: sortableOptions.treeTag,=0A=
      only: sortableOptions.only,=0A=
      name: element.id,=0A=
      format: sortableOptions.format=0A=
    }, arguments[1] || {});=0A=
    =0A=
    var root =3D {=0A=
      id: null,=0A=
      parent: null,=0A=
      children: [],=0A=
      container: element,=0A=
      position: 0=0A=
    }=0A=
    =0A=
    return Sortable._tree(element, options, root);=0A=
  },=0A=
=0A=
  /* Construct a [i] index for a particular node */=0A=
  _constructIndex: function(node) {=0A=
    var index =3D '';=0A=
    do {=0A=
      if (node.id) index =3D '[' + node.position + ']' + index;=0A=
    } while ((node =3D node.parent) !=3D null);=0A=
    return index;=0A=
  },=0A=
=0A=
  sequence: function(element) {=0A=
    element =3D $(element);=0A=
    var options =3D Object.extend(this.options(element), arguments[1] || =
{});=0A=
    =0A=
    return $(this.findElements(element, options) || []).map( =
function(item) {=0A=
      return item.id.match(options.format) ? =
item.id.match(options.format)[1] : '';=0A=
    });=0A=
  },=0A=
=0A=
  setSequence: function(element, new_sequence) {=0A=
    element =3D $(element);=0A=
    var options =3D Object.extend(this.options(element), arguments[2] || =
{});=0A=
    =0A=
    var nodeMap =3D {};=0A=
    this.findElements(element, options).each( function(n) {=0A=
        if (n.id.match(options.format))=0A=
            nodeMap[n.id.match(options.format)[1]] =3D [n, n.parentNode];=0A=
        n.parentNode.removeChild(n);=0A=
    });=0A=
   =0A=
    new_sequence.each(function(ident) {=0A=
      var n =3D nodeMap[ident];=0A=
      if (n) {=0A=
        n[1].appendChild(n[0]);=0A=
        delete nodeMap[ident];=0A=
      }=0A=
    });=0A=
  },=0A=
  =0A=
  serialize: function(element) {=0A=
    element =3D $(element);=0A=
    var options =3D Object.extend(Sortable.options(element), =
arguments[1] || {});=0A=
    var name =3D encodeURIComponent(=0A=
      (arguments[1] && arguments[1].name) ? arguments[1].name : =
element.id);=0A=
    =0A=
    if (options.tree) {=0A=
      return Sortable.tree(element, arguments[1]).children.map( function =
(item) {=0A=
        return [name + Sortable._constructIndex(item) + "[id]=3D" + =0A=
                =
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));=0A=
      }).flatten().join('&');=0A=
    } else {=0A=
      return Sortable.sequence(element, arguments[1]).map( =
function(item) {=0A=
        return name + "[]=3D" + encodeURIComponent(item);=0A=
      }).join('&');=0A=
    }=0A=
  }=0A=
}=0A=
=0A=
// Returns true if child is contained within element=0A=
Element.isParent =3D function(child, element) {=0A=
  if (!child.parentNode || child =3D=3D element) return false;=0A=
  if (child.parentNode =3D=3D element) return true;=0A=
  return Element.isParent(child.parentNode, element);=0A=
}=0A=
=0A=
Element.findChildren =3D function(element, only, recursive, tagName) {   =
 =0A=
  if(!element.hasChildNodes()) return null;=0A=
  tagName =3D tagName.toUpperCase();=0A=
  if(only) only =3D [only].flatten();=0A=
  var elements =3D [];=0A=
  $A(element.childNodes).each( function(e) {=0A=
    if(e.tagName && e.tagName.toUpperCase()=3D=3DtagName &&=0A=
      (!only || (Element.classNames(e).detect(function(v) { return =
only.include(v) }))))=0A=
        elements.push(e);=0A=
    if(recursive) {=0A=
      var grandchildren =3D Element.findChildren(e, only, recursive, =
tagName);=0A=
      if(grandchildren) elements.push(grandchildren);=0A=
    }=0A=
  });=0A=
=0A=
  return (elements.length>0 ? elements.flatten() : []);=0A=
}=0A=
=0A=
Element.offsetSize =3D function (element, type) {=0A=
  return element['offset' + ((type=3D=3D'vertical' || =
type=3D=3D'height') ? 'Height' : 'Width')];=0A=
}=0A=

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/controls.js?1209768151

// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, =
http://mir.aculo.us)=0A=
//           (c) 2005, 2006 Ivan Krstic =
(http://blogs.law.harvard.edu/ivan)=0A=
//           (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)=0A=
// Contributors:=0A=
//  Richard Livsey=0A=
//  Rahul Bhargava=0A=
//  Rob Wills=0A=
// =0A=
// script.aculo.us is freely distributable under the terms of an =
MIT-style license.=0A=
// For details, see the script.aculo.us web site: http://script.aculo.us/=0A=
=0A=
// Autocompleter.Base handles all the autocompletion functionality =0A=
// that's independent of the data source for autocompletion. This=0A=
// includes drawing the autocompletion menu, observing keyboard=0A=
// and mouse events, and similar.=0A=
//=0A=
// Specific autocompleters need to provide, at the very least, =0A=
// a getUpdatedChoices function that will be invoked every time=0A=
// the text inside the monitored textbox changes. This method =0A=
// should get the text for which to provide autocompletion by=0A=
// invoking this.getToken(), NOT by directly accessing=0A=
// this.element.value. This is to allow incremental tokenized=0A=
// autocompletion. Specific auto-completion logic (AJAX, etc)=0A=
// belongs in getUpdatedChoices.=0A=
//=0A=
// Tokenized incremental autocompletion is enabled automatically=0A=
// when an autocompleter is instantiated with the 'tokens' option=0A=
// in the options parameter, e.g.:=0A=
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });=0A=
// will incrementally autocomplete with a comma as the token.=0A=
// Additionally, ',' in the above example can be replaced with=0A=
// a token array, e.g. { tokens: [',', '\n'] } which=0A=
// enables autocompletion on multiple tokens. This is most =0A=
// useful when one of the tokens is \n (a newline), as it =0A=
// allows smart autocompletion after linebreaks.=0A=
=0A=
if(typeof Effect =3D=3D 'undefined')=0A=
  throw("controls.js requires including script.aculo.us' effects.js =
library");=0A=
=0A=
var Autocompleter =3D {}=0A=
Autocompleter.Base =3D function() {};=0A=
Autocompleter.Base.prototype =3D {=0A=
  baseInitialize: function(element, update, options) {=0A=
    this.element     =3D $(element); =0A=
    this.update      =3D $(update);  =0A=
    this.hasFocus    =3D false; =0A=
    this.changed     =3D false; =0A=
    this.active      =3D false; =0A=
    this.index       =3D 0;     =0A=
    this.entryCount  =3D 0;=0A=
=0A=
    if(this.setOptions)=0A=
      this.setOptions(options);=0A=
    else=0A=
      this.options =3D options || {};=0A=
=0A=
    this.options.paramName    =3D this.options.paramName || =
this.element.name;=0A=
    this.options.tokens       =3D this.options.tokens || [];=0A=
    this.options.frequency    =3D this.options.frequency || 0.4;=0A=
    this.options.minChars     =3D this.options.minChars || 1;=0A=
    this.options.onShow       =3D this.options.onShow || =0A=
      function(element, update){ =0A=
        if(!update.style.position || =
update.style.position=3D=3D'absolute') {=0A=
          update.style.position =3D 'absolute';=0A=
          Position.clone(element, update, {=0A=
            setHeight: false, =0A=
            offsetTop: element.offsetHeight=0A=
          });=0A=
        }=0A=
        Effect.Appear(update,{duration:0.15});=0A=
      };=0A=
    this.options.onHide =3D this.options.onHide || =0A=
      function(element, update){ new Effect.Fade(update,{duration:0.15}) =
};=0A=
=0A=
    if(typeof(this.options.tokens) =3D=3D 'string') =0A=
      this.options.tokens =3D new Array(this.options.tokens);=0A=
=0A=
    this.observer =3D null;=0A=
    =0A=
    this.element.setAttribute('autocomplete','off');=0A=
=0A=
    Element.hide(this.update);=0A=
=0A=
    Event.observe(this.element, "blur", =
this.onBlur.bindAsEventListener(this));=0A=
    Event.observe(this.element, "keypress", =
this.onKeyPress.bindAsEventListener(this));=0A=
  },=0A=
=0A=
  show: function() {=0A=
    if(Element.getStyle(this.update, 'display')=3D=3D'none') =
this.options.onShow(this.element, this.update);=0A=
    if(!this.iefix && =0A=
      (navigator.appVersion.indexOf('MSIE')>0) &&=0A=
      (navigator.userAgent.indexOf('Opera')<0) &&=0A=
      (Element.getStyle(this.update, 'position')=3D=3D'absolute')) {=0A=
      new Insertion.After(this.update, =0A=
       '<iframe id=3D"' + this.update.id + '_iefix" '+=0A=
       =
'style=3D"display:none;position:absolute;filter:progid:DXImageTransform.M=
icrosoft.Alpha(opacity=3D0);" ' +=0A=
       'src=3D"javascript:false;" frameborder=3D"0" =
scrolling=3D"no"></iframe>');=0A=
      this.iefix =3D $(this.update.id+'_iefix');=0A=
    }=0A=
    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);=0A=
  },=0A=
  =0A=
  fixIEOverlapping: function() {=0A=
    Position.clone(this.update, this.iefix, =
{setTop:(!this.update.style.height)});=0A=
    this.iefix.style.zIndex =3D 1;=0A=
    this.update.style.zIndex =3D 2;=0A=
    Element.show(this.iefix);=0A=
  },=0A=
=0A=
  hide: function() {=0A=
    this.stopIndicator();=0A=
    if(Element.getStyle(this.update, 'display')!=3D'none') =
this.options.onHide(this.element, this.update);=0A=
    if(this.iefix) Element.hide(this.iefix);=0A=
  },=0A=
=0A=
  startIndicator: function() {=0A=
    if(this.options.indicator) Element.show(this.options.indicator);=0A=
  },=0A=
=0A=
  stopIndicator: function() {=0A=
    if(this.options.indicator) Element.hide(this.options.indicator);=0A=
  },=0A=
=0A=
  onKeyPress: function(event) {=0A=
    if(this.active)=0A=
      switch(event.keyCode) {=0A=
       case Event.KEY_TAB:=0A=
       case Event.KEY_RETURN:=0A=
         this.selectEntry();=0A=
         Event.stop(event);=0A=
       case Event.KEY_ESC:=0A=
         this.hide();=0A=
         this.active =3D false;=0A=
         Event.stop(event);=0A=
         return;=0A=
       case Event.KEY_LEFT:=0A=
       case Event.KEY_RIGHT:=0A=
         return;=0A=
       case Event.KEY_UP:=0A=
         this.markPrevious();=0A=
         this.render();=0A=
         if(navigator.appVersion.indexOf('AppleWebKit')>0) =
Event.stop(event);=0A=
         return;=0A=
       case Event.KEY_DOWN:=0A=
         this.markNext();=0A=
         this.render();=0A=
         if(navigator.appVersion.indexOf('AppleWebKit')>0) =
Event.stop(event);=0A=
         return;=0A=
      }=0A=
     else =0A=
       if(event.keyCode=3D=3DEvent.KEY_TAB || =
event.keyCode=3D=3DEvent.KEY_RETURN || =0A=
         (navigator.appVersion.indexOf('AppleWebKit') > 0 && =
event.keyCode =3D=3D 0)) return;=0A=
=0A=
    this.changed =3D true;=0A=
    this.hasFocus =3D true;=0A=
=0A=
    if(this.observer) clearTimeout(this.observer);=0A=
      this.observer =3D =0A=
        setTimeout(this.onObserverEvent.bind(this), =
this.options.frequency*1000);=0A=
  },=0A=
=0A=
  activate: function() {=0A=
    this.changed =3D false;=0A=
    this.hasFocus =3D true;=0A=
    this.getUpdatedChoices();=0A=
  },=0A=
=0A=
  onHover: function(event) {=0A=
    var element =3D Event.findElement(event, 'LI');=0A=
    if(this.index !=3D element.autocompleteIndex) =0A=
    {=0A=
        this.index =3D element.autocompleteIndex;=0A=
        this.render();=0A=
    }=0A=
    Event.stop(event);=0A=
  },=0A=
  =0A=
  onClick: function(event) {=0A=
    var element =3D Event.findElement(event, 'LI');=0A=
    this.index =3D element.autocompleteIndex;=0A=
    this.selectEntry();=0A=
    this.hide();=0A=
  },=0A=
  =0A=
  onBlur: function(event) {=0A=
    // needed to make click events working=0A=
    setTimeout(this.hide.bind(this), 250);=0A=
    this.hasFocus =3D false;=0A=
    this.active =3D false;     =0A=
  }, =0A=
  =0A=
  render: function() {=0A=
    if(this.entryCount > 0) {=0A=
      for (var i =3D 0; i < this.entryCount; i++)=0A=
        this.index=3D=3Di ? =0A=
          Element.addClassName(this.getEntry(i),"selected") : =0A=
          Element.removeClassName(this.getEntry(i),"selected");=0A=
        =0A=
      if(this.hasFocus) { =0A=
        this.show();=0A=
        this.active =3D true;=0A=
      }=0A=
    } else {=0A=
      this.active =3D false;=0A=
      this.hide();=0A=
    }=0A=
  },=0A=
  =0A=
  markPrevious: function() {=0A=
    if(this.index > 0) this.index--=0A=
      else this.index =3D this.entryCount-1;=0A=
    this.getEntry(this.index).scrollIntoView(true);=0A=
  },=0A=
  =0A=
  markNext: function() {=0A=
    if(this.index < this.entryCount-1) this.index++=0A=
      else this.index =3D 0;=0A=
    this.getEntry(this.index).scrollIntoView(false);=0A=
  },=0A=
  =0A=
  getEntry: function(index) {=0A=
    return this.update.firstChild.childNodes[index];=0A=
  },=0A=
  =0A=
  getCurrentEntry: function() {=0A=
    return this.getEntry(this.index);=0A=
  },=0A=
  =0A=
  selectEntry: function() {=0A=
    this.active =3D false;=0A=
    this.updateElement(this.getCurrentEntry());=0A=
  },=0A=
=0A=
  updateElement: function(selectedElement) {=0A=
    if (this.options.updateElement) {=0A=
      this.options.updateElement(selectedElement);=0A=
      return;=0A=
    }=0A=
    var value =3D '';=0A=
    if (this.options.select) {=0A=
      var nodes =3D document.getElementsByClassName(this.options.select, =
selectedElement) || [];=0A=
      if(nodes.length>0) value =3D Element.collectTextNodes(nodes[0], =
this.options.select);=0A=
    } else=0A=
      value =3D Element.collectTextNodesIgnoreClass(selectedElement, =
'informal');=0A=
    =0A=
    var lastTokenPos =3D this.findLastToken();=0A=
    if (lastTokenPos !=3D -1) {=0A=
      var newValue =3D this.element.value.substr(0, lastTokenPos + 1);=0A=
      var whitespace =3D this.element.value.substr(lastTokenPos + =
1).match(/^\s+/);=0A=
      if (whitespace)=0A=
        newValue +=3D whitespace[0];=0A=
      this.element.value =3D newValue + value;=0A=
    } else {=0A=
      this.element.value =3D value;=0A=
    }=0A=
    this.element.focus();=0A=
    =0A=
    if (this.options.afterUpdateElement)=0A=
      this.options.afterUpdateElement(this.element, selectedElement);=0A=
  },=0A=
=0A=
  updateChoices: function(choices) {=0A=
    if(!this.changed && this.hasFocus) {=0A=
      this.update.innerHTML =3D choices;=0A=
      Element.cleanWhitespace(this.update);=0A=
      Element.cleanWhitespace(this.update.down());=0A=
=0A=
      if(this.update.firstChild && this.update.down().childNodes) {=0A=
        this.entryCount =3D =0A=
          this.update.down().childNodes.length;=0A=
        for (var i =3D 0; i < this.entryCount; i++) {=0A=
          var entry =3D this.getEntry(i);=0A=
          entry.autocompleteIndex =3D i;=0A=
          this.addObservers(entry);=0A=
        }=0A=
      } else { =0A=
        this.entryCount =3D 0;=0A=
      }=0A=
=0A=
      this.stopIndicator();=0A=
      this.index =3D 0;=0A=
      =0A=
      if(this.entryCount=3D=3D1 && this.options.autoSelect) {=0A=
        this.selectEntry();=0A=
        this.hide();=0A=
      } else {=0A=
        this.render();=0A=
      }=0A=
    }=0A=
  },=0A=
=0A=
  addObservers: function(element) {=0A=
    Event.observe(element, "mouseover", =
this.onHover.bindAsEventListener(this));=0A=
    Event.observe(element, "click", =
this.onClick.bindAsEventListener(this));=0A=
  },=0A=
=0A=
  onObserverEvent: function() {=0A=
    this.changed =3D false;   =0A=
    if(this.getToken().length>=3Dthis.options.minChars) {=0A=
      this.startIndicator();=0A=
      this.getUpdatedChoices();=0A=
    } else {=0A=
      this.active =3D false;=0A=
      this.hide();=0A=
    }=0A=
  },=0A=
=0A=
  getToken: function() {=0A=
    var tokenPos =3D this.findLastToken();=0A=
    if (tokenPos !=3D -1)=0A=
      var ret =3D this.element.value.substr(tokenPos + =
1).replace(/^\s+/,'').replace(/\s+$/,'');=0A=
    else=0A=
      var ret =3D this.element.value;=0A=
=0A=
    return /\n/.test(ret) ? '' : ret;=0A=
  },=0A=
=0A=
  findLastToken: function() {=0A=
    var lastTokenPos =3D -1;=0A=
=0A=
    for (var i=3D0; i<this.options.tokens.length; i++) {=0A=
      var thisTokenPos =3D =
this.element.value.lastIndexOf(this.options.tokens[i]);=0A=
      if (thisTokenPos > lastTokenPos)=0A=
        lastTokenPos =3D thisTokenPos;=0A=
    }=0A=
    return lastTokenPos;=0A=
  }=0A=
}=0A=
=0A=
Ajax.Autocompleter =3D Class.create();=0A=
Object.extend(Object.extend(Ajax.Autocompleter.prototype, =
Autocompleter.Base.prototype), {=0A=
  initialize: function(element, update, url, options) {=0A=
    this.baseInitialize(element, update, options);=0A=
    this.options.asynchronous  =3D true;=0A=
    this.options.onComplete    =3D this.onComplete.bind(this);=0A=
    this.options.defaultParams =3D this.options.parameters || null;=0A=
    this.url                   =3D url;=0A=
  },=0A=
=0A=
  getUpdatedChoices: function() {=0A=
    entry =3D encodeURIComponent(this.options.paramName) + '=3D' + =0A=
      encodeURIComponent(this.getToken());=0A=
=0A=
    this.options.parameters =3D this.options.callback ?=0A=
      this.options.callback(this.element, entry) : entry;=0A=
=0A=
    if(this.options.defaultParams) =0A=
      this.options.parameters +=3D '&' + this.options.defaultParams;=0A=
=0A=
    new Ajax.Request(this.url, this.options);=0A=
  },=0A=
=0A=
  onComplete: function(request) {=0A=
    this.updateChoices(request.responseText);=0A=
  }=0A=
=0A=
});=0A=
=0A=
// The local array autocompleter. Used when you'd prefer to=0A=
// inject an array of autocompletion options into the page, rather=0A=
// than sending out Ajax queries, which can be quite slow sometimes.=0A=
//=0A=
// The constructor takes four parameters. The first two are, as usual,=0A=
// the id of the monitored textbox, and id of the autocompletion menu.=0A=
// The third is the array you want to autocomplete from, and the fourth=0A=
// is the options block.=0A=
//=0A=
// Extra local autocompletion options:=0A=
// - choices - How many autocompletion choices to offer=0A=
//=0A=
// - partialSearch - If false, the autocompleter will match entered=0A=
//                    text only at the beginning of strings in the =0A=
//                    autocomplete array. Defaults to true, which will=0A=
//                    match text at the beginning of any *word* in the=0A=
//                    strings in the autocomplete array. If you want to=0A=
//                    search anywhere in the string, additionally set=0A=
//                    the option fullSearch to true (default: off).=0A=
//=0A=
// - fullSsearch - Search anywhere in autocomplete array strings.=0A=
//=0A=
// - partialChars - How many characters to enter before triggering=0A=
//                   a partial match (unlike minChars, which defines=0A=
//                   how many characters are required to do any match=0A=
//                   at all). Defaults to 2.=0A=
//=0A=
// - ignoreCase - Whether to ignore case when autocompleting.=0A=
//                 Defaults to true.=0A=
//=0A=
// It's possible to pass in a custom function as the 'selector' =0A=
// option, if you prefer to write your own autocompletion logic.=0A=
// In that case, the other options above will not apply unless=0A=
// you support them.=0A=
=0A=
Autocompleter.Local =3D Class.create();=0A=
Autocompleter.Local.prototype =3D Object.extend(new =
Autocompleter.Base(), {=0A=
  initialize: function(element, update, array, options) {=0A=
    this.baseInitialize(element, update, options);=0A=
    this.options.array =3D array;=0A=
  },=0A=
=0A=
  getUpdatedChoices: function() {=0A=
    this.updateChoices(this.options.selector(this));=0A=
  },=0A=
=0A=
  setOptions: function(options) {=0A=
    this.options =3D Object.extend({=0A=
      choices: 10,=0A=
      partialSearch: true,=0A=
      partialChars: 2,=0A=
      ignoreCase: true,=0A=
      fullSearch: false,=0A=
      selector: function(instance) {=0A=
        var ret       =3D []; // Beginning matches=0A=
        var partial   =3D []; // Inside matches=0A=
        var entry     =3D instance.getToken();=0A=
        var count     =3D 0;=0A=
=0A=
        for (var i =3D 0; i < instance.options.array.length &&  =0A=
          ret.length < instance.options.choices ; i++) { =0A=
=0A=
          var elem =3D instance.options.array[i];=0A=
          var foundPos =3D instance.options.ignoreCase ? =0A=
            elem.toLowerCase().indexOf(entry.toLowerCase()) : =0A=
            elem.indexOf(entry);=0A=
=0A=
          while (foundPos !=3D -1) {=0A=
            if (foundPos =3D=3D 0 && elem.length !=3D entry.length) { =0A=
              ret.push("<li><strong>" + elem.substr(0, entry.length) + =
"</strong>" + =0A=
                elem.substr(entry.length) + "</li>");=0A=
              break;=0A=
            } else if (entry.length >=3D instance.options.partialChars =
&& =0A=
              instance.options.partialSearch && foundPos !=3D -1) {=0A=
              if (instance.options.fullSearch || =
/\s/.test(elem.substr(foundPos-1,1))) {=0A=
                partial.push("<li>" + elem.substr(0, foundPos) + =
"<strong>" +=0A=
                  elem.substr(foundPos, entry.length) + "</strong>" + =
elem.substr(=0A=
                  foundPos + entry.length) + "</li>");=0A=
                break;=0A=
              }=0A=
            }=0A=
=0A=
            foundPos =3D instance.options.ignoreCase ? =0A=
              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + =
1) : =0A=
              elem.indexOf(entry, foundPos + 1);=0A=
=0A=
          }=0A=
        }=0A=
        if (partial.length)=0A=
          ret =3D ret.concat(partial.slice(0, instance.options.choices - =
ret.length))=0A=
        return "<ul>" + ret.join('') + "</ul>";=0A=
      }=0A=
    }, options || {});=0A=
  }=0A=
});=0A=
=0A=
// AJAX in-place editor=0A=
//=0A=
// see documentation on =
http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor=0A=
=0A=
// Use this if you notice weird scrolling problems on some browsers,=0A=
// the DOM might be a bit confused when this gets called so do this=0A=
// waits 1 ms (with setTimeout) until it does the activation=0A=
Field.scrollFreeActivate =3D function(field) {=0A=
  setTimeout(function() {=0A=
    Field.activate(field);=0A=
  }, 1);=0A=
}=0A=
=0A=
Ajax.InPlaceEditor =3D Class.create();=0A=
Ajax.InPlaceEditor.defaultHighlightColor =3D "#FFFF99";=0A=
Ajax.InPlaceEditor.prototype =3D {=0A=
  initialize: function(element, url, options) {=0A=
    this.url =3D url;=0A=
    this.element =3D $(element);=0A=
=0A=
    this.options =3D Object.extend({=0A=
      paramName: "value",=0A=
      okButton: true,=0A=
      okText: "ok",=0A=
      cancelLink: true,=0A=
      cancelText: "cancel",=0A=
      savingText: "Saving...",=0A=
      clickToEditText: "Click to edit",=0A=
      okText: "ok",=0A=
      rows: 1,=0A=
      onComplete: function(transport, element) {=0A=
        new Effect.Highlight(element, {startcolor: =
this.options.highlightcolor});=0A=
      },=0A=
      onFailure: function(transport) {=0A=
        alert("Error communicating with the server: " + =
transport.responseText.stripTags());=0A=
      },=0A=
      callback: function(form) {=0A=
        return Form.serialize(form);=0A=
      },=0A=
      handleLineBreaks: true,=0A=
      loadingText: 'Loading...',=0A=
      savingClassName: 'inplaceeditor-saving',=0A=
      loadingClassName: 'inplaceeditor-loading',=0A=
      formClassName: 'inplaceeditor-form',=0A=
      highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,=0A=
      highlightendcolor: "#FFFFFF",=0A=
      externalControl: null,=0A=
      submitOnBlur: false,=0A=
      ajaxOptions: {},=0A=
      evalScripts: false=0A=
    }, options || {});=0A=
=0A=
    if(!this.options.formId && this.element.id) {=0A=
      this.options.formId =3D this.element.id + "-inplaceeditor";=0A=
      if ($(this.options.formId)) {=0A=
        // there's already a form with that name, don't specify an id=0A=
        this.options.formId =3D null;=0A=
      }=0A=
    }=0A=
    =0A=
    if (this.options.externalControl) {=0A=
      this.options.externalControl =3D $(this.options.externalControl);=0A=
    }=0A=
    =0A=
    this.originalBackground =3D Element.getStyle(this.element, =
'background-color');=0A=
    if (!this.originalBackground) {=0A=
      this.originalBackground =3D "transparent";=0A=
    }=0A=
    =0A=
    this.element.title =3D this.options.clickToEditText;=0A=
    =0A=
    this.onclickListener =3D =
this.enterEditMode.bindAsEventListener(this);=0A=
    this.mouseoverListener =3D this.enterHover.bindAsEventListener(this);=0A=
    this.mouseoutListener =3D this.leaveHover.bindAsEventListener(this);=0A=
    Event.observe(this.element, 'click', this.onclickListener);=0A=
    Event.observe(this.element, 'mouseover', this.mouseoverListener);=0A=
    Event.observe(this.element, 'mouseout', this.mouseoutListener);=0A=
    if (this.options.externalControl) {=0A=
      Event.observe(this.options.externalControl, 'click', =
this.onclickListener);=0A=
      Event.observe(this.options.externalControl, 'mouseover', =
this.mouseoverListener);=0A=
      Event.observe(this.options.externalControl, 'mouseout', =
this.mouseoutListener);=0A=
    }=0A=
  },=0A=
  enterEditMode: function(evt) {=0A=
    if (this.saving) return;=0A=
    if (this.editing) return;=0A=
    this.editing =3D true;=0A=
    this.onEnterEditMode();=0A=
    if (this.options.externalControl) {=0A=
      Element.hide(this.options.externalControl);=0A=
    }=0A=
    Element.hide(this.element);=0A=
    this.createForm();=0A=
    this.element.parentNode.insertBefore(this.form, this.element);=0A=
    if (!this.options.loadTextURL) =
Field.scrollFreeActivate(this.editField);=0A=
    // stop the event to avoid a page refresh in Safari=0A=
    if (evt) {=0A=
      Event.stop(evt);=0A=
    }=0A=
    return false;=0A=
  },=0A=
  createForm: function() {=0A=
    this.form =3D document.createElement("form");=0A=
    this.form.id =3D this.options.formId;=0A=
    Element.addClassName(this.form, this.options.formClassName)=0A=
    this.form.onsubmit =3D this.onSubmit.bind(this);=0A=
=0A=
    this.createEditField();=0A=
=0A=
    if (this.options.textarea) {=0A=
      var br =3D document.createElement("br");=0A=
      this.form.appendChild(br);=0A=
    }=0A=
=0A=
    if (this.options.okButton) {=0A=
      okButton =3D document.createElement("input");=0A=
      okButton.type =3D "submit";=0A=
      okButton.value =3D this.options.okText;=0A=
      okButton.className =3D 'editor_ok_button';=0A=
      this.form.appendChild(okButton);=0A=
    }=0A=
=0A=
    if (this.options.cancelLink) {=0A=
      cancelLink =3D document.createElement("a");=0A=
      cancelLink.href =3D "#";=0A=
      =
cancelLink.appendChild(document.createTextNode(this.options.cancelText));=0A=
      cancelLink.onclick =3D this.onclickCancel.bind(this);=0A=
      cancelLink.className =3D 'editor_cancel';      =0A=
      this.form.appendChild(cancelLink);=0A=
    }=0A=
  },=0A=
  hasHTMLLineBreaks: function(string) {=0A=
    if (!this.options.handleLineBreaks) return false;=0A=
    return string.match(/<br/i) || string.match(/<p>/i);=0A=
  },=0A=
  convertHTMLLineBreaks: function(string) {=0A=
    return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, =
"\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");=0A=
  },=0A=
  createEditField: function() {=0A=
    var text;=0A=
    if(this.options.loadTextURL) {=0A=
      text =3D this.options.loadingText;=0A=
    } else {=0A=
      text =3D this.getText();=0A=
    }=0A=
=0A=
    var obj =3D this;=0A=
    =0A=
    if (this.options.rows =3D=3D 1 && !this.hasHTMLLineBreaks(text)) {=0A=
      this.options.textarea =3D false;=0A=
      var textField =3D document.createElement("input");=0A=
      textField.obj =3D this;=0A=
      textField.type =3D "text";=0A=
      textField.name =3D this.options.paramName;=0A=
      textField.value =3D text;=0A=
      textField.style.backgroundColor =3D this.options.highlightcolor;=0A=
      textField.className =3D 'editor_field';=0A=
      var size =3D this.options.size || this.options.cols || 0;=0A=
      if (size !=3D 0) textField.size =3D size;=0A=
      if (this.options.submitOnBlur)=0A=
        textField.onblur =3D this.onSubmit.bind(this);=0A=
      this.editField =3D textField;=0A=
    } else {=0A=
      this.options.textarea =3D true;=0A=
      var textArea =3D document.createElement("textarea");=0A=
      textArea.obj =3D this;=0A=
      textArea.name =3D this.options.paramName;=0A=
      textArea.value =3D this.convertHTMLLineBreaks(text);=0A=
      textArea.rows =3D this.options.rows;=0A=
      textArea.cols =3D this.options.cols || 40;=0A=
      textArea.className =3D 'editor_field';      =0A=
      if (this.options.submitOnBlur)=0A=
        textArea.onblur =3D this.onSubmit.bind(this);=0A=
      this.editField =3D textArea;=0A=
    }=0A=
    =0A=
    if(this.options.loadTextURL) {=0A=
      this.loadExternalText();=0A=
    }=0A=
    this.form.appendChild(this.editField);=0A=
  },=0A=
  getText: function() {=0A=
    return this.element.innerHTML;=0A=
  },=0A=
  loadExternalText: function() {=0A=
    Element.addClassName(this.form, this.options.loadingClassName);=0A=
    this.editField.disabled =3D true;=0A=
    new Ajax.Request(=0A=
      this.options.loadTextURL,=0A=
      Object.extend({=0A=
        asynchronous: true,=0A=
        onComplete: this.onLoadedExternalText.bind(this)=0A=
      }, this.options.ajaxOptions)=0A=
    );=0A=
  },=0A=
  onLoadedExternalText: function(transport) {=0A=
    Element.removeClassName(this.form, this.options.loadingClassName);=0A=
    this.editField.disabled =3D false;=0A=
    this.editField.value =3D transport.responseText.stripTags();=0A=
    Field.scrollFreeActivate(this.editField);=0A=
  },=0A=
  onclickCancel: function() {=0A=
    this.onComplete();=0A=
    this.leaveEditMode();=0A=
    return false;=0A=
  },=0A=
  onFailure: function(transport) {=0A=
    this.options.onFailure(transport);=0A=
    if (this.oldInnerHTML) {=0A=
      this.element.innerHTML =3D this.oldInnerHTML;=0A=
      this.oldInnerHTML =3D null;=0A=
    }=0A=
    return false;=0A=
  },=0A=
  onSubmit: function() {=0A=
    // onLoading resets these so we need to save them away for the Ajax =
call=0A=
    var form =3D this.form;=0A=
    var value =3D this.editField.value;=0A=
    =0A=
    // do this first, sometimes the ajax call returns before we get a =
chance to switch on Saving...=0A=
    // which means this will actually switch on Saving... *after* we've =
left edit mode causing Saving...=0A=
    // to be displayed indefinitely=0A=
    this.onLoading();=0A=
    =0A=
    if (this.options.evalScripts) {=0A=
      new Ajax.Request(=0A=
        this.url, Object.extend({=0A=
          parameters: this.options.callback(form, value),=0A=
          onComplete: this.onComplete.bind(this),=0A=
          onFailure: this.onFailure.bind(this),=0A=
          asynchronous:true, =0A=
          evalScripts:true=0A=
        }, this.options.ajaxOptions));=0A=
    } else  {=0A=
      new Ajax.Updater(=0A=
        { success: this.element,=0A=
          // don't update on failure (this could be an option)=0A=
          failure: null }, =0A=
        this.url, Object.extend({=0A=
          parameters: this.options.callback(form, value),=0A=
          onComplete: this.onComplete.bind(this),=0A=
          onFailure: this.onFailure.bind(this)=0A=
        }, this.options.ajaxOptions));=0A=
    }=0A=
    // stop the event to avoid a page refresh in Safari=0A=
    if (arguments.length > 1) {=0A=
      Event.stop(arguments[0]);=0A=
    }=0A=
    return false;=0A=
  },=0A=
  onLoading: function() {=0A=
    this.saving =3D true;=0A=
    this.removeForm();=0A=
    this.leaveHover();=0A=
    this.showSaving();=0A=
  },=0A=
  showSaving: function() {=0A=
    this.oldInnerHTML =3D this.element.innerHTML;=0A=
    this.element.innerHTML =3D this.options.savingText;=0A=
    Element.addClassName(this.element, this.options.savingClassName);=0A=
    this.element.style.backgroundColor =3D this.originalBackground;=0A=
    Element.show(this.element);=0A=
  },=0A=
  removeForm: function() {=0A=
    if(this.form) {=0A=
      if (this.form.parentNode) Element.remove(this.form);=0A=
      this.form =3D null;=0A=
    }=0A=
  },=0A=
  enterHover: function() {=0A=
    if (this.saving) return;=0A=
    this.element.style.backgroundColor =3D this.options.highlightcolor;=0A=
    if (this.effect) {=0A=
      this.effect.cancel();=0A=
    }=0A=
    Element.addClassName(this.element, this.options.hoverClassName)=0A=
  },=0A=
  leaveHover: function() {=0A=
    if (this.options.backgroundColor) {=0A=
      this.element.style.backgroundColor =3D this.oldBackground;=0A=
    }=0A=
    Element.removeClassName(this.element, this.options.hoverClassName)=0A=
    if (this.saving) return;=0A=
    this.effect =3D new Effect.Highlight(this.element, {=0A=
      startcolor: this.options.highlightcolor,=0A=
      endcolor: this.options.highlightendcolor,=0A=
      restorecolor: this.originalBackground=0A=
    });=0A=
  },=0A=
  leaveEditMode: function() {=0A=
    Element.removeClassName(this.element, this.options.savingClassName);=0A=
    this.removeForm();=0A=
    this.leaveHover();=0A=
    this.element.style.backgroundColor =3D this.originalBackground;=0A=
    Element.show(this.element);=0A=
    if (this.options.externalControl) {=0A=
      Element.show(this.options.externalControl);=0A=
    }=0A=
    this.editing =3D false;=0A=
    this.saving =3D false;=0A=
    this.oldInnerHTML =3D null;=0A=
    this.onLeaveEditMode();=0A=
  },=0A=
  onComplete: function(transport) {=0A=
    this.leaveEditMode();=0A=
    this.options.onComplete.bind(this)(transport, this.element);=0A=
  },=0A=
  onEnterEditMode: function() {},=0A=
  onLeaveEditMode: function() {},=0A=
  dispose: function() {=0A=
    if (this.oldInnerHTML) {=0A=
      this.element.innerHTML =3D this.oldInnerHTML;=0A=
    }=0A=
    this.leaveEditMode();=0A=
    Event.stopObserving(this.element, 'click', this.onclickListener);=0A=
    Event.stopObserving(this.element, 'mouseover', =
this.mouseoverListener);=0A=
    Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);=0A=
    if (this.options.externalControl) {=0A=
      Event.stopObserving(this.options.externalControl, 'click', =
this.onclickListener);=0A=
      Event.stopObserving(this.options.externalControl, 'mouseover', =
this.mouseoverListener);=0A=
      Event.stopObserving(this.options.externalControl, 'mouseout', =
this.mouseoutListener);=0A=
    }=0A=
  }=0A=
};=0A=
=0A=
Ajax.InPlaceCollectionEditor =3D Class.create();=0A=
Object.extend(Ajax.InPlaceCollectionEditor.prototype, =
Ajax.InPlaceEditor.prototype);=0A=
Object.extend(Ajax.InPlaceCollectionEditor.prototype, {=0A=
  createEditField: function() {=0A=
    if (!this.cached_selectTag) {=0A=
      var selectTag =3D document.createElement("select");=0A=
      var collection =3D this.options.collection || [];=0A=
      var optionTag;=0A=
      collection.each(function(e,i) {=0A=
        optionTag =3D document.createElement("option");=0A=
        optionTag.value =3D (e instanceof Array) ? e[0] : e;=0A=
        if((typeof this.options.value =3D=3D 'undefined') && =0A=
          ((e instanceof Array) ? this.element.innerHTML =3D=3D e[1] : e =
=3D=3D optionTag.value)) optionTag.selected =3D true;=0A=
        if(this.options.value=3D=3DoptionTag.value) optionTag.selected =
=3D true;=0A=
        optionTag.appendChild(document.createTextNode((e instanceof =
Array) ? e[1] : e));=0A=
        selectTag.appendChild(optionTag);=0A=
      }.bind(this));=0A=
      this.cached_selectTag =3D selectTag;=0A=
    }=0A=
=0A=
    this.editField =3D this.cached_selectTag;=0A=
    if(this.options.loadTextURL) this.loadExternalText();=0A=
    this.form.appendChild(this.editField);=0A=
    this.options.callback =3D function(form, value) {=0A=
      return "value=3D" + encodeURIComponent(value);=0A=
    }=0A=
  }=0A=
});=0A=
=0A=
// Delayed observer, like Form.Element.Observer, =0A=
// but waits for delay after last key input=0A=
// Ideal for live-search fields=0A=
=0A=
Form.Element.DelayedObserver =3D Class.create();=0A=
Form.Element.DelayedObserver.prototype =3D {=0A=
  initialize: function(element, delay, callback) {=0A=
    this.delay     =3D delay || 0.5;=0A=
    this.element   =3D $(element);=0A=
    this.callback  =3D callback;=0A=
    this.timer     =3D null;=0A=
    this.lastValue =3D $F(this.element); =0A=
    =
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListen=
er(this));=0A=
  },=0A=
  delayedListener: function(event) {=0A=
    if(this.lastValue =3D=3D $F(this.element)) return;=0A=
    if(this.timer) clearTimeout(this.timer);=0A=
    this.timer =3D setTimeout(this.onTimerEvent.bind(this), this.delay * =
1000);=0A=
    this.lastValue =3D $F(this.element);=0A=
  },=0A=
  onTimerEvent: function() {=0A=
    this.timer =3D null;=0A=
    this.callback(this.element, $F(this.element));=0A=
  }=0A=
};=0A=

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/application.js?1209768151

//function equalize() {=0A=
//    if(document.getElementById('left_col') && =
document.getElementById('right_col')){=0A=
//        var maxHeight =3D =
Math.max(document.getElementById('left_col').scrollHeight,document.getEle=
mentById('right_col').scrollHeight);=0A=
//        =
document.getElementById('left_col').style.height=3DmaxHeight+'px';=0A=
//        =
document.getElementById('right_col').style.height=3DmaxHeight+'px';=0A=
//    }=0A=
//    if(document.getElementById('col1') && =
document.getElementById('col2') && document.getElementById('col3')){=0A=
//        var maxHeight =3D =
Math.max(document.getElementById('col1').scrollHeight,document.getElement=
ById('col2').scrollHeight,document.getElementById('col3').scrollHeight);=0A=
//        if(document.getElementById('left_col') && =
document.getElementById('right_col')){=0A=
//            var maxHeight =3D =
Math.max(document.getElementById('left_col').scrollHeight,document.getEle=
mentById('right_col').scrollHeight,maxHeight);=0A=
//        }=0A=
//        document.getElementById('col1').style.height=3DmaxHeight+'px';=0A=
//        document.getElementById('col2').style.height=3DmaxHeight+'px';=0A=
//        document.getElementById('col3').style.height=3DmaxHeight+'px';=0A=
//    }=0A=
//    if(document.getElementById('col1') && =
document.getElementById('col3')){=0A=
//        var maxHeight =3D =
Math.max(document.getElementById('col1').scrollHeight,document.getElement=
ById('col3').scrollHeight);=0A=
//        document.getElementById('col1').style.height=3DmaxHeight+'px';=0A=
//        document.getElementById('col3').style.height=3DmaxHeight+'px';=0A=
// //       alert("equalized: maxHeight =3D " + maxHeight);=0A=
//    }=0A=
//}=0A=
//=0A=
//window.onload=3Dequalize;=0A=
=0A=
function process_link_kinds(event_id) {=0A=
    if($F('link_kind_ids').indexOf(event_id) !=3D -1){=0A=
        $('dates').show();=0A=
    }=0A=
    else {=0A=
        $('dates').hide();=0A=
    }=0A=
}=0A=
=0A=
function setup_expand_collapse(section) {=0A=
    Element.observe("head_"+section, 'click', function(){=0A=
        if($("head_"+section).hasClassName('section_head_expanded')){=0A=
            $("head_"+section).addClassName('section_head_collapsed');=0A=
            $("head_"+section).removeClassName('section_head_expanded');=0A=
            $("section_"+section).hide();=0A=
            setTall();=0A=
//            equalize();=0A=
        }=0A=
        else {=0A=
            $("head_"+section).addClassName('section_head_expanded');=0A=
            $("head_"+section).removeClassName('section_head_collapsed');=0A=
            $("section_"+section).show();=0A=
            setTall();=0A=
//            equalize();=0A=
        }=0A=
    })=0A=
}=0A=

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/column.js?1209768151

/*=0A=
	by Paul@YellowPencil.com and Scott@YellowPencil.com=0A=
	includes TextResizeDetector by Lawrence Carvalho =
<carvalho@uk.yahoo-inc.com>=0A=
	feel free to delete all comments except for the above credit=0A=
*/=0A=
=0A=
// Replace 'center' 'right' and 'left' with the ID names of the columns =
you want to balance.=0A=
// The last one is there to show how you can add more columns.  Just =
delete the ones you're not using.=0A=
var divs =3D new Array('col1', 'col2', 'col3');=0A=
=0A=
// Initialize Scripts - is this a browser that understands DOM?=0A=
function scriptInit() { if (!document.getElementById) { return; } }=0A=
=0A=
// Set up Event Listener=0A=
function addEvent(elm, evType, fn, useCapture) { =0A=
	if (elm.addEventListener) { elm.addEventListener(evType, fn, =
useCapture); return true; } =0A=
	else if (elm.attachEvent) { var r =3D elm.attachEvent('on' + evType, =
fn); return r; }=0A=
	else { elm['on' + evType] =3D fn; }=0A=
}=0A=
=0A=
// Start Column Script=0A=
function setTall() {=0A=
	if (document.getElementById) { var maxHeight =3D 0; for (var i =3D 0; i =
< divs.length; i++) {=0A=
			if (document.getElementById(divs[i]) !=3D null)=0A=
			{ var div =3D document.getElementById(divs[i]); div.style.height =3D =
null; if (div.offsetHeight > maxHeight) maxHeight =3D div.offsetHeight; }=0A=
		}=0A=
	for (var i =3D 0; i < divs.length; i++) {=0A=
			if (document.getElementById(divs[i]) !=3D null)=0A=
			{ var div =3D document.getElementById(divs[i]); div.style.height =3D =
maxHeight + 'px'; if (div.offsetHeight > maxHeight) { div.style.height =
=3D (maxHeight - (div.offsetHeight - maxHeight)) + 'px'; } }=0A=
		}=0A=
	}=0A=
}=0A=
=0A=
// Assign one of the columns to the TextResizeDetector.=0A=
function initTall() {=0A=
	if (document.getElementById) { for (var i =3D 0; i < divs.length; i++)=0A=
		{ if (document.getElementById(divs[i]) !=3D null) { =
TextResizeDetector.TARGET_ELEMENT_ID =3D divs[i]; break; } }=0A=
	setTall(); } =0A=
}=0A=
=0A=
// Fire Events=0A=
addEvent(window, 'load', initTall, false);=0A=
addEvent(window, 'resize', setTall, false);=0A=
=0A=
/*	Detects changes to font sizes when user changes browser settings=0A=
	Fires a custom event with the following data:=0A=
	iBase  : base font size=0A=
	iDelta : difference in pixels from previous setting=0A=
	iSize  : size in pixel of text=0A=
	author Lawrence Carvalho carvalho@uk.yahoo-inc.com */=0A=
=0A=
// @constructor=0A=
TextResizeDetector =3D function() {=0A=
    var el  =3D null;=0A=
	var iIntervalDelay  =3D 200;=0A=
	var iInterval =3D null;=0A=
	var iCurrSize =3D -1;=0A=
	var iBase =3D -1;=0A=
 	var aListeners =3D [];=0A=
 	var createControlElement =3D function() {=0A=
	 	el =3D document.createElement('span');=0A=
		el.id=3D'textResizeControl';=0A=
		el.innerHTML=3D'&nbsp;';=0A=
		el.style.position=3D"absolute";=0A=
		el.style.left=3D"-9999px";=0A=
		var elC =3D =
document.getElementById(TextResizeDetector.TARGET_ELEMENT_ID);=0A=
		// insert before firstChild=0A=
		if (elC)=0A=
			elC.insertBefore(el,elC.firstChild);=0A=
		iBase =3D iCurrSize =3D TextResizeDetector.getSize();=0A=
 	};=0A=
=0A=
 	function _stopDetector() {=0A=
		window.clearInterval(iInterval);=0A=
		iInterval=3Dnull;=0A=
	};=0A=
	function _startDetector() {=0A=
		if (!iInterval) {=0A=
			iInterval =3D =
window.setInterval('TextResizeDetector.detect()',iIntervalDelay);=0A=
		}=0A=
	};=0A=
=0A=
 	 function _detect() {=0A=
 		var iNewSize =3D TextResizeDetector.getSize();=0A=
=0A=
 		if(iNewSize!=3D=3D iCurrSize) {=0A=
			for (var 	i=3D0;i <aListeners.length;i++) {=0A=
				aListnr =3D aListeners[i];=0A=
				var oArgs =3D {  iBase: iBase,iDelta:((iCurrSize!=3D-1) ? iNewSize - =
iCurrSize + 'px' : "0px"),iSize:iCurrSize =3D iNewSize};=0A=
				if (!aListnr.obj) {=0A=
					aListnr.fn('textSizeChanged',[oArgs]);=0A=
				}=0A=
				else  {=0A=
					aListnr.fn.apply(aListnr.obj,['textSizeChanged',[oArgs]]);=0A=
				}=0A=
			}=0A=
=0A=
 		}=0A=
 		return iCurrSize;=0A=
 	};=0A=
	var onAvailable =3D function() {=0A=
		if (!TextResizeDetector.onAvailableCount_i ) {=0A=
			TextResizeDetector.onAvailableCount_i =3D0;=0A=
		}=0A=
=0A=
		if (document.getElementById(TextResizeDetector.TARGET_ELEMENT_ID)) {=0A=
			TextResizeDetector.init();=0A=
			if (TextResizeDetector.USER_INIT_FUNC){=0A=
				TextResizeDetector.USER_INIT_FUNC();=0A=
			}=0A=
			TextResizeDetector.onAvailableCount_i =3D null;=0A=
		}=0A=
		else {=0A=
			if (TextResizeDetector.onAvailableCount_i<600) {=0A=
	  	 	    TextResizeDetector.onAvailableCount_i++;=0A=
				setTimeout(onAvailable,200)=0A=
			}=0A=
		}=0A=
	};=0A=
	setTimeout(onAvailable,500);=0A=
=0A=
 	return {=0A=
		 	/*=0A=
		 	 * Initializes the detector=0A=
		 	 *=0A=
		 	 * @param {String} sId The id of the element in which to create the =
control element=0A=
		 	 */=0A=
		 	init: function() {=0A=
=0A=
		 		createControlElement();=0A=
				_startDetector();=0A=
 			},=0A=
			/**=0A=
			 * Adds listeners to the ontextsizechange event.=0A=
			 * Returns the base font size=0A=
			 *=0A=
			 */=0A=
 			addEventListener:function(fn,obj,bScope) {=0A=
				aListeners[aListeners.length] =3D {=0A=
					fn: fn,=0A=
					obj: obj=0A=
				}=0A=
				return iBase;=0A=
			},=0A=
			/**=0A=
			 * performs the detection and fires textSizeChanged event=0A=
			 * @return the current font size=0A=
			 * @type {integer}=0A=
			 */=0A=
 			detect:function() {=0A=
 				return _detect();=0A=
 			},=0A=
 			/**=0A=
 			 * Returns the height of the control element=0A=
 			 *=0A=
			 * @return the current height of control element=0A=
			 * @type {integer}=0A=
 			 */=0A=
 			getSize:function() {=0A=
	 				var iSize;=0A=
			 		return el.offsetHeight;=0A=
=0A=
=0A=
 			},=0A=
 			/**=0A=
 			 * Stops the detector=0A=
 			 */=0A=
 			stopDetector:function() {=0A=
				return _stopDetector();=0A=
			},=0A=
			/*=0A=
			 * Starts the detector=0A=
			 */=0A=
 			startDetector:function() {=0A=
				return _startDetector();=0A=
			}=0A=
 	}=0A=
 }();=0A=
=0A=
/*** end TextResizeDetector */=0A=
=0A=
TextResizeDetector.TARGET_ELEMENT_ID =3D 'doc';=0A=
TextResizeDetector.USER_INIT_FUNC =3D function() {=0A=
	var iBase =3D TextResizeDetector.addEventListener(setTall, null);=0A=
};=0A=
=0A=

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/yahoo-min.js?1209768151

/*=0A=
Copyright (c) 2007, Yahoo! Inc. All rights reserved.=0A=
Code licensed under the BSD License:=0A=
http://developer.yahoo.net/yui/license.txt=0A=
version: 2.4.0=0A=
*/=0A=
if(typeof YAHOO=3D=3D"undefined"||!YAHOO){var =
YAHOO=3D{};}YAHOO.namespace=3Dfunction(){var =
A=3Darguments,E=3Dnull,C,B,D;for(C=3D0;C<A.length;C=3DC+1){D=3DA[C].split=
(".");E=3DYAHOO;for(B=3D(D[0]=3D=3D"YAHOO")?1:0;B<D.length;B=3DB+1){E[D[B=
]]=3DE[D[B]]||{};E=3DE[D[B]];}}return =
E;};YAHOO.log=3Dfunction(D,A,C){var =
B=3DYAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return =
false;}};YAHOO.register=3Dfunction(A,E,D){var =
I=3DYAHOO.env.modules;if(!I[A]){I[A]=3D{versions:[],builds:[]};}var =
B=3DI[A],H=3DD.version,G=3DD.build,F=3DYAHOO.env.listeners;B.name=3DA;B.v=
ersion=3DH;B.build=3DG;B.versions.push(H);B.builds.push(G);B.mainClass=3D=
E;for(var =
C=3D0;C<F.length;C=3DC+1){F[C](B);}if(E){E.VERSION=3DH;E.BUILD=3DG;}else{=
YAHOO.log("mainClass is undefined for module =
"+A,"warn");}};YAHOO.env=3DYAHOO.env||{modules:[],listeners:[]};YAHOO.env=
.getVersion=3Dfunction(A){return =
YAHOO.env.modules[A]||null;};YAHOO.env.ua=3Dfunction(){var =
C=3D{ie:0,opera:0,gecko:0,webkit:0,mobile:null};var =
B=3Dnavigator.userAgent,A;if((/KHTML/).test(B)){C.webkit=3D1;}A=3DB.match=
(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){C.webkit=3DparseFloat(A[1]);if(/ =
Mobile\//.test(B)){C.mobile=3D"Apple";}else{A=3DB.match(/NokiaN[^\/]*/);i=
f(A){C.mobile=3DA[0];}}}if(!C.webkit){A=3DB.match(/Opera[\s\/]([^\s]*)/);=
if(A&&A[1]){C.opera=3DparseFloat(A[1]);A=3DB.match(/Opera =
Mini[^;]*/);if(A){C.mobile=3DA[0];}}else{A=3DB.match(/MSIE\s([^;]*)/);if(=
A&&A[1]){C.ie=3DparseFloat(A[1]);}else{A=3DB.match(/Gecko\/([^\s]*)/);if(=
A){C.gecko=3D1;A=3DB.match(/rv:([^\s\)]*)/);if(A&&A[1]){C.gecko=3DparseFl=
oat(A[1]);}}}}}return =
C;}();(function(){YAHOO.namespace("util","widget","example");if("undefine=
d"!=3D=3Dtypeof YAHOO_config){var =
B=3DYAHOO_config.listener,A=3DYAHOO.env.listeners,D=3Dtrue,C;if(B){for(C=3D=
0;C<A.length;C=3DC+1){if(A[C]=3D=3DB){D=3Dfalse;break;}}if(D){A.push(B);}=
}}})();YAHOO.lang=3DYAHOO.lang||{isArray:function(B){if(B){var =
A=3DYAHOO.lang;return =
A.isNumber(B.length)&&A.isFunction(B.splice);}return =
false;},isBoolean:function(A){return typeof =
A=3D=3D=3D"boolean";},isFunction:function(A){return typeof =
A=3D=3D=3D"function";},isNull:function(A){return =
A=3D=3D=3Dnull;},isNumber:function(A){return typeof =
A=3D=3D=3D"number"&&isFinite(A);},isObject:function(A){return(A&&(typeof =
A=3D=3D=3D"object"||YAHOO.lang.isFunction(A)))||false;},isString:function=
(A){return typeof A=3D=3D=3D"string";},isUndefined:function(A){return =
typeof =
A=3D=3D=3D"undefined";},hasOwnProperty:function(A,B){if(Object.prototype.=
hasOwnProperty){return A.hasOwnProperty(B);}return =
!YAHOO.lang.isUndefined(A[B])&&A.constructor.prototype[B]!=3D=3DA[B];},_I=
EEnumFix:function(C,B){if(YAHOO.env.ua.ie){var =
E=3D["toString","valueOf"],A;for(A=3D0;A<E.length;A=3DA+1){var =
F=3DE[A],D=3DB[F];if(YAHOO.lang.isFunction(D)&&D!=3DObject.prototype[F]){=
C[F]=3DD;}}}},extend:function(D,E,C){if(!E||!D){throw new =
Error("YAHOO.lang.extend failed, please check that all dependencies are =
included.");}var =
B=3Dfunction(){};B.prototype=3DE.prototype;D.prototype=3Dnew =
B();D.prototype.constructor=3DD;D.superclass=3DE.prototype;if(E.prototype=
.constructor=3D=3DObject.prototype.constructor){E.prototype.constructor=3D=
E;}if(C){for(var A in =
C){D.prototype[A]=3DC[A];}YAHOO.lang._IEEnumFix(D.prototype,C);}},augment=
Object:function(E,D){if(!D||!E){throw new Error("Absorb failed, verify =
dependencies.");}var =
A=3Darguments,C,F,B=3DA[2];if(B&&B!=3D=3Dtrue){for(C=3D2;C<A.length;C=3DC=
+1){E[A[C]]=3DD[A[C]];}}else{for(F in =
D){if(B||!E[F]){E[F]=3DD[F];}}YAHOO.lang._IEEnumFix(E,D);}},augmentProto:=
function(D,C){if(!C||!D){throw new Error("Augment failed, verify =
dependencies.");}var A=3D[D.prototype,C.prototype];for(var =
B=3D2;B<arguments.length;B=3DB+1){A.push(arguments[B]);}YAHOO.lang.augmen=
tObject.apply(this,A);},dump:function(A,G){var =
C=3DYAHOO.lang,D,F,I=3D[],J=3D"{...}",B=3D"f(){...}",H=3D", ",E=3D" =3D> =
";if(!C.isObject(A)){return A+"";}else{if(A instanceof Date||("nodeType" =
in A&&"tagName" in A)){return A;}else{if(C.isFunction(A)){return =
B;}}}G=3D(C.isNumber(G))?G:3;if(C.isArray(A)){I.push("[");for(D=3D0,F=3DA=
.length;D<F;D=3DD+1){if(C.isObject(A[D])){I.push((G>0)?C.dump(A[D],G-1):J=
);}else{I.push(A[D]);}I.push(H);}if(I.length>1){I.pop();}I.push("]");}els=
e{I.push("{");for(D in =
A){if(C.hasOwnProperty(A,D)){I.push(D+E);if(C.isObject(A[D])){I.push((G>0=
)?C.dump(A[D],G-1):J);}else{I.push(A[D]);}I.push(H);}}if(I.length>1){I.po=
p();}I.push("}");}return I.join("");},substitute:function(Q,B,J){var =
G,F,E,M,N,P,D=3DYAHOO.lang,L=3D[],C,H=3D"dump",K=3D" =
",A=3D"{",O=3D"}";for(;;){G=3DQ.lastIndexOf(A);if(G<0){break;}F=3DQ.index=
Of(O,G);if(G+1>=3DF){break;}C=3DQ.substring(G+1,F);M=3DC;P=3Dnull;E=3DM.i=
ndexOf(K);if(E>-1){P=3DM.substring(E+1);M=3DM.substring(0,E);}N=3DB[M];if=
(J){N=3DJ(M,N,P);}if(D.isObject(N)){if(D.isArray(N)){N=3DD.dump(N,parseIn=
t(P,10));}else{P=3DP||"";var =
I=3DP.indexOf(H);if(I>-1){P=3DP.substring(4);}if(N.toString=3D=3D=3DObjec=
t.prototype.toString||I>-1){N=3DD.dump(N,parseInt(P,10));}else{N=3DN.toSt=
ring();}}}else{if(!D.isString(N)&&!D.isNumber(N)){N=3D"~-"+L.length+"-~";=
L[L.length]=3DC;}}Q=3DQ.substring(0,G)+N+Q.substring(F+1);}for(G=3DL.leng=
th-1;G>=3D0;G=3DG-1){Q=3DQ.replace(new =
RegExp("~-"+G+"-~"),"{"+L[G]+"}","g");}return =
Q;},trim:function(A){try{return =
A.replace(/^\s+|\s+$/g,"");}catch(B){return A;}},merge:function(){var =
D=3D{},B=3Darguments;for(var =
C=3D0,A=3DB.length;C<A;C=3DC+1){YAHOO.lang.augmentObject(D,B[C],true);}re=
turn D;},later:function(H,B,I,D,E){H=3DH||0;B=3DB||{};var =
C=3DI,G=3DD,F,A;if(YAHOO.lang.isString(I)){C=3DB[I];}if(!C){throw new =
TypeError("method =
undefined");}if(!YAHOO.lang.isArray(G)){G=3D[D];}F=3Dfunction(){C.apply(B=
,G);};A=3D(E)?setInterval(F,H):setTimeout(F,H);return{interval:E,cancel:f=
unction(){if(this.interval){clearInterval(A);}else{clearTimeout(A);}}};},=
isValue:function(B){var =
A=3DYAHOO.lang;return(A.isObject(B)||A.isString(B)||A.isNumber(B)||A.isBo=
olean(B));}};YAHOO.util.Lang=3DYAHOO.lang;YAHOO.lang.augment=3DYAHOO.lang=
.augmentProto;YAHOO.augment=3DYAHOO.lang.augmentProto;YAHOO.extend=3DYAHO=
O.lang.extend;YAHOO.register("yahoo",YAHOO,{version:"2.4.0",build:"733"})=
;
------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/event-min.js?1209768151

/*=0A=
Copyright (c) 2007, Yahoo! Inc. All rights reserved.=0A=
Code licensed under the BSD License:=0A=
http://developer.yahoo.net/yui/license.txt=0A=
version: 2.4.0=0A=
*/=0A=
YAHOO.util.CustomEvent=3Dfunction(D,B,C,A){this.type=3DD;this.scope=3DB||=
window;this.silent=3DC;this.signature=3DA||YAHOO.util.CustomEvent.LIST;th=
is.subscribers=3D[];if(!this.silent){}var =
E=3D"_YUICEOnSubscribe";if(D!=3D=3DE){this.subscribeEvent=3Dnew =
YAHOO.util.CustomEvent(E,this,true);}this.lastError=3Dnull;};YAHOO.util.C=
ustomEvent.LIST=3D0;YAHOO.util.CustomEvent.FLAT=3D1;YAHOO.util.CustomEven=
t.prototype=3D{subscribe:function(B,C,A){if(!B){throw new Error("Invalid =
callback for subscriber to =
'"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,A=
);}this.subscribers.push(new =
YAHOO.util.Subscriber(B,C,A));},unsubscribe:function(D,F){if(!D){return =
this.unsubscribeAll();}var E=3Dfalse;for(var =
B=3D0,A=3Dthis.subscribers.length;B<A;++B){var =
C=3Dthis.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=3Dtrue;}=
}return E;},fire:function(){var =
D=3Dthis.subscribers.length;if(!D&&this.silent){return true;}var =
G=3D[],F=3Dtrue,C,H=3Dfalse;for(C=3D0;C<arguments.length;++C){G.push(argu=
ments[C]);}if(!this.silent){}for(C=3D0;C<D;++C){var =
K=3Dthis.subscribers[C];if(!K){H=3Dtrue;}else{if(!this.silent){}var =
J=3DK.getScope(this.scope);if(this.signature=3D=3DYAHOO.util.CustomEvent.=
FLAT){var =
A=3Dnull;if(G.length>0){A=3DG[0];}try{F=3DK.fn.call(J,A,K.obj);}catch(E){=
this.lastError=3DE;}}else{try{F=3DK.fn.call(J,this.type,G,K.obj);}catch(E=
){this.lastError=3DE;}}if(false=3D=3D=3DF){if(!this.silent){}return =
false;}}}if(H){var =
I=3D[],B=3Dthis.subscribers;for(C=3D0,D=3DB.length;C<D;C=3DC+1){I.push(B[=
C]);}this.subscribers=3DI;}return =
true;},unsubscribeAll:function(){for(var =
B=3D0,A=3Dthis.subscribers.length;B<A;++B){this._delete(A-1-B);}this.subs=
cribers=3D[];return B;},_delete:function(A){var =
B=3Dthis.subscribers[A];if(B){delete B.fn;delete =
B.obj;}this.subscribers[A]=3Dnull;},toString:function(){return"CustomEven=
t: '"+this.type+"', scope: =
"+this.scope;}};YAHOO.util.Subscriber=3Dfunction(B,C,A){this.fn=3DB;this.=
obj=3DYAHOO.lang.isUndefined(C)?null:C;this.override=3DA;};YAHOO.util.Sub=
scriber.prototype.getScope=3Dfunction(A){if(this.override){if(this.overri=
de=3D=3D=3Dtrue){return this.obj;}else{return this.override;}}return =
A;};YAHOO.util.Subscriber.prototype.contains=3Dfunction(A,B){if(B){return=
(this.fn=3D=3DA&&this.obj=3D=3DB);}else{return(this.fn=3D=3DA);}};YAHOO.u=
til.Subscriber.prototype.toString=3Dfunction(){return"Subscriber { obj: =
"+this.obj+", override: "+(this.override||"no")+" =
}";};if(!YAHOO.util.Event){YAHOO.util.Event=3Dfunction(){var =
H=3Dfalse;var I=3D[];var J=3D[];var G=3D[];var E=3D[];var C=3D0;var =
F=3D[];var B=3D[];var A=3D0;var =
D=3D{63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9};return{P=
OLL_RETRYS:4000,POLL_INTERVAL:10,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_=
SCOPE:4,OBJ:5,OVERRIDE:6,lastError:null,isSafari:YAHOO.env.ua.webkit,webk=
it:YAHOO.env.ua.webkit,isIE:YAHOO.env.ua.ie,_interval:null,_dri:null,DOMR=
eady:false,startInterval:function(){if(!this._interval){var K=3Dthis;var =
L=3Dfunction(){K._tryPreloadAttach();};this._interval=3DsetInterval(L,thi=
s.POLL_INTERVAL);}},onAvailable:function(P,M,Q,O,N){var =
K=3D(YAHOO.lang.isString(P))?[P]:P;for(var =
L=3D0;L<K.length;L=3DL+1){F.push({id:K[L],fn:M,obj:Q,override:O,checkRead=
y:N});}C=3Dthis.POLL_RETRYS;this.startInterval();},onContentReady:functio=
n(M,K,N,L){this.onAvailable(M,K,N,L,true);},onDOMReady:function(K,M,L){if=
(this.DOMReady){setTimeout(function(){var =
N=3Dwindow;if(L){if(L=3D=3D=3Dtrue){N=3DM;}else{N=3DL;}}K.call(N,"DOMRead=
y",[],M);},0);}else{this.DOMReadyEvent.subscribe(K,M,L);}},addListener:fu=
nction(M,K,V,Q,L){if(!V||!V.call){return =
false;}if(this._isValidCollection(M)){var W=3Dtrue;for(var =
R=3D0,T=3DM.length;R<T;++R){W=3Dthis.on(M[R],K,V,Q,L)&&W;}return =
W;}else{if(YAHOO.lang.isString(M)){var =
P=3Dthis.getEl(M);if(P){M=3DP;}else{this.onAvailable(M,function(){YAHOO.u=
til.Event.on(M,K,V,Q,L);});return true;}}}if(!M){return =
false;}if("unload"=3D=3DK&&Q!=3D=3Dthis){J[J.length]=3D[M,K,V,Q,L];return=
 true;}var Y=3DM;if(L){if(L=3D=3D=3Dtrue){Y=3DQ;}else{Y=3DL;}}var =
N=3Dfunction(Z){return V.call(Y,YAHOO.util.Event.getEvent(Z,M),Q);};var =
X=3D[M,K,V,N,Y,Q,L];var =
S=3DI.length;I[S]=3DX;if(this.useLegacyEvent(M,K)){var =
O=3Dthis.getLegacyIndex(M,K);if(O=3D=3D-1||M!=3DG[O][0]){O=3DG.length;B[M=
.id+K]=3DO;G[O]=3D[M,K,M["on"+K]];E[O]=3D[];M["on"+K]=3Dfunction(Z){YAHOO=
.util.Event.fireLegacyEvent(YAHOO.util.Event.getEvent(Z),O);};}E[O].push(=
X);}else{try{this._simpleAdd(M,K,N,false);}catch(U){this.lastError=3DU;th=
is.removeListener(M,K,V);return false;}}return =
true;},fireLegacyEvent:function(O,M){var =
Q=3Dtrue,K,S,R,T,P;S=3DE[M];for(var =
L=3D0,N=3DS.length;L<N;++L){R=3DS[L];if(R&&R[this.WFN]){T=3DR[this.ADJ_SC=
OPE];P=3DR[this.WFN].call(T,O);Q=3D(Q&&P);}}K=3DG[M];if(K&&K[2]){K[2](O);=
}return Q;},getLegacyIndex:function(L,M){var =
K=3Dthis.generateId(L)+M;if(typeof B[K]=3D=3D"undefined"){return =
-1;}else{return =
B[K];}},useLegacyEvent:function(L,M){if(this.webkit&&("click"=3D=3DM||"db=
lclick"=3D=3DM)){var =
K=3DparseInt(this.webkit,10);if(!isNaN(K)&&K<418){return true;}}return =
false;},removeListener:function(L,K,T){var O,R,V;if(typeof =
L=3D=3D"string"){L=3Dthis.getEl(L);}else{if(this._isValidCollection(L)){v=
ar =
U=3Dtrue;for(O=3D0,R=3DL.length;O<R;++O){U=3D(this.removeListener(L[O],K,=
T)&&U);}return U;}}if(!T||!T.call){return =
this.purgeElement(L,false,K);}if("unload"=3D=3DK){for(O=3D0,R=3DJ.length;=
O<R;O++){V=3DJ[O];if(V&&V[0]=3D=3DL&&V[1]=3D=3DK&&V[2]=3D=3DT){J[O]=3Dnul=
l;return true;}}return false;}var P=3Dnull;var =
Q=3Darguments[3];if("undefined"=3D=3D=3Dtypeof =
Q){Q=3Dthis._getCacheIndex(L,K,T);}if(Q>=3D0){P=3DI[Q];}if(!L||!P){return=
 false;}if(this.useLegacyEvent(L,K)){var =
N=3Dthis.getLegacyIndex(L,K);var =
M=3DE[N];if(M){for(O=3D0,R=3DM.length;O<R;++O){V=3DM[O];if(V&&V[this.EL]=3D=
=3DL&&V[this.TYPE]=3D=3DK&&V[this.FN]=3D=3DT){M[O]=3Dnull;break;}}}}else{=
try{this._simpleRemove(L,K,P[this.WFN],false);}catch(S){this.lastError=3D=
S;return false;}}delete I[Q][this.WFN];delete =
I[Q][this.FN];I[Q]=3Dnull;return true;},getTarget:function(M,L){var =
K=3DM.target||M.srcElement;return =
this.resolveTextNode(K);},resolveTextNode:function(K){if(K&&3=3D=3DK.node=
Type){return K.parentNode;}else{return K;}},getPageX:function(L){var =
K=3DL.pageX;if(!K&&0!=3D=3DK){K=3DL.clientX||0;if(this.isIE){K+=3Dthis._g=
etScrollLeft();}}return K;},getPageY:function(K){var =
L=3DK.pageY;if(!L&&0!=3D=3DL){L=3DK.clientY||0;if(this.isIE){L+=3Dthis._g=
etScrollTop();}}return =
L;},getXY:function(K){return[this.getPageX(K),this.getPageY(K)];=0A=
},getRelatedTarget:function(L){var =
K=3DL.relatedTarget;if(!K){if(L.type=3D=3D"mouseout"){K=3DL.toElement;}el=
se{if(L.type=3D=3D"mouseover"){K=3DL.fromElement;}}}return =
this.resolveTextNode(K);},getTime:function(M){if(!M.time){var L=3Dnew =
Date().getTime();try{M.time=3DL;}catch(K){this.lastError=3DK;return =
L;}}return =
M.time;},stopEvent:function(K){this.stopPropagation(K);this.preventDefaul=
t(K);},stopPropagation:function(K){if(K.stopPropagation){K.stopPropagatio=
n();}else{K.cancelBubble=3Dtrue;}},preventDefault:function(K){if(K.preven=
tDefault){K.preventDefault();}else{K.returnValue=3Dfalse;}},getEvent:func=
tion(M,K){var L=3DM||window.event;if(!L){var =
N=3Dthis.getEvent.caller;while(N){L=3DN.arguments[0];if(L&&Event=3D=3DL.c=
onstructor){break;}N=3DN.caller;}}return L;},getCharCode:function(L){var =
K=3DL.keyCode||L.charCode||0;if(YAHOO.env.ua.webkit&&(K in =
D)){K=3DD[K];}return K;},_getCacheIndex:function(O,P,N){for(var =
M=3D0,L=3DI.length;M<L;++M){var =
K=3DI[M];if(K&&K[this.FN]=3D=3DN&&K[this.EL]=3D=3DO&&K[this.TYPE]=3D=3DP)=
{return M;}}return -1;},generateId:function(K){var =
L=3DK.id;if(!L){L=3D"yuievtautoid-"+A;++A;K.id=3DL;}return =
L;},_isValidCollection:function(L){try{return(L&&typeof =
L!=3D=3D"string"&&L.length&&!L.tagName&&!L.alert&&typeof =
L[0]!=3D=3D"undefined");}catch(K){return =
false;}},elCache:{},getEl:function(K){return(typeof =
K=3D=3D=3D"string")?document.getElementById(K):K;},clearCache:function(){=
},DOMReadyEvent:new =
YAHOO.util.CustomEvent("DOMReady",this),_load:function(L){if(!H){H=3Dtrue=
;var =
K=3DYAHOO.util.Event;K._ready();K._tryPreloadAttach();}},_ready:function(=
L){var =
K=3DYAHOO.util.Event;if(!K.DOMReady){K.DOMReady=3Dtrue;K.DOMReadyEvent.fi=
re();K._simpleRemove(document,"DOMContentLoaded",K._ready);}},_tryPreload=
Attach:function(){if(this.locked){return =
false;}if(this.isIE){if(!this.DOMReady){this.startInterval();return =
false;}}this.locked=3Dtrue;var P=3D!H;if(!P){P=3D(C>0);}var O=3D[];var =
Q=3Dfunction(S,T){var =
R=3DS;if(T.override){if(T.override=3D=3D=3Dtrue){R=3DT.obj;}else{R=3DT.ov=
erride;}}T.fn.call(R,T.obj);};var =
L,K,N,M;for(L=3D0,K=3DF.length;L<K;++L){N=3DF[L];if(N&&!N.checkReady){M=3D=
this.getEl(N.id);if(M){Q(M,N);F[L]=3Dnull;}else{O.push(N);}}}for(L=3D0,K=3D=
F.length;L<K;++L){N=3DF[L];if(N&&N.checkReady){M=3Dthis.getEl(N.id);if(M)=
{if(H||M.nextSibling){Q(M,N);F[L]=3Dnull;}}else{O.push(N);}}}C=3D(O.lengt=
h=3D=3D=3D0)?0:C-1;if(P){this.startInterval();}else{clearInterval(this._i=
nterval);this._interval=3Dnull;}this.locked=3Dfalse;return =
true;},purgeElement:function(O,P,R){var =
M=3D(YAHOO.lang.isString(O))?this.getEl(O):O;var =
Q=3Dthis.getListeners(M,R),N,K;if(Q){for(N=3D0,K=3DQ.length;N<K;++N){var =
L=3DQ[N];this.removeListener(M,L.type,L.fn,L.index);}}if(P&&M&&M.childNod=
es){for(N=3D0,K=3DM.childNodes.length;N<K;++N){this.purgeElement(M.childN=
odes[N],P,R);}}},getListeners:function(M,K){var =
P=3D[],L;if(!K){L=3D[I,J];}else{if(K=3D=3D=3D"unload"){L=3D[J];}else{L=3D=
[I];}}var R=3D(YAHOO.lang.isString(M))?this.getEl(M):M;for(var =
O=3D0;O<L.length;O=3DO+1){var T=3DL[O];if(T&&T.length>0){for(var =
Q=3D0,S=3DT.length;Q<S;++Q){var =
N=3DT[Q];if(N&&N[this.EL]=3D=3D=3DR&&(!K||K=3D=3D=3DN[this.TYPE])){P.push=
({type:N[this.TYPE],fn:N[this.FN],obj:N[this.OBJ],adjust:N[this.OVERRIDE]=
,scope:N[this.ADJ_SCOPE],index:Q});}}}}return(P.length)?P:null;},_unload:=
function(R){var =
Q=3DYAHOO.util.Event,O,N,L,K,M;for(O=3D0,K=3DJ.length;O<K;++O){L=3DJ[O];i=
f(L){var =
P=3Dwindow;if(L[Q.ADJ_SCOPE]){if(L[Q.ADJ_SCOPE]=3D=3D=3Dtrue){P=3DL[Q.UNL=
OAD_OBJ];}else{P=3DL[Q.ADJ_SCOPE];}}L[Q.FN].call(P,Q.getEvent(R,L[Q.EL]),=
L[Q.UNLOAD_OBJ]);J[O]=3Dnull;L=3Dnull;P=3Dnull;}}J=3Dnull;if(YAHOO.env.ua=
.IE&&I&&I.length>0){N=3DI.length;while(N){M=3DN-1;L=3DI[M];if(L){L[Q.EL].=
clearAttributes();}N=3DN-1;}L=3Dnull;}G=3Dnull;Q._simpleRemove(window,"un=
load",Q._unload);},_getScrollLeft:function(){return =
this._getScroll()[1];},_getScrollTop:function(){return =
this._getScroll()[0];},_getScroll:function(){var =
K=3Ddocument.documentElement,L=3Ddocument.body;if(K&&(K.scrollTop||K.scro=
llLeft)){return[K.scrollTop,K.scrollLeft];}else{if(L){return[L.scrollTop,=
L.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:functio=
n(){if(window.addEventListener){return =
function(M,N,L,K){M.addEventListener(N,L,(K));};}else{if(window.attachEve=
nt){return function(M,N,L,K){M.attachEvent("on"+N,L);};}else{return =
function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener=
){return =
function(M,N,L,K){M.removeEventListener(N,L,(K));};}else{if(window.detach=
Event){return function(L,M,K){L.detachEvent("on"+M,K);};}else{return =
function(){};}}}()};}();(function(){var =
A=3DYAHOO.util.Event;A.on=3DA.addListener;if(A.isIE){YAHOO.util.Event.onD=
OMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);A._dri=3D=
setInterval(function(){var =
C=3Ddocument.createElement("p");try{C.doScroll("left");clearInterval(A._d=
ri);A._dri=3Dnull;A._ready();C=3Dnull;}catch(B){C=3Dnull;}},A.POLL_INTERV=
AL);}else{if(A.webkit){A._dri=3DsetInterval(function(){var =
B=3Ddocument.readyState;if("loaded"=3D=3DB||"complete"=3D=3DB){clearInter=
val(A._dri);A._dri=3Dnull;A._ready();}},A.POLL_INTERVAL);}else{A._simpleA=
dd(document,"DOMContentLoaded",A._ready);}}A._simpleAdd(window,"load",A._=
load);A._simpleAdd(window,"unload",A._unload);A._tryPreloadAttach();})();=
}YAHOO.util.EventProvider=3Dfunction(){};YAHOO.util.EventProvider.prototy=
pe=3D{__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E=
){this.__yui_events=3Dthis.__yui_events||{};var =
D=3Dthis.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscr=
ibers=3Dthis.__yui_subscribers||{};var =
B=3Dthis.__yui_subscribers;if(!B[A]){B[A]=3D[];}B[A].push({fn:C,obj:F,ove=
rride:E});}},unsubscribe:function(C,E,G){this.__yui_events=3Dthis.__yui_e=
vents||{};var A=3Dthis.__yui_events;if(C){var F=3DA[C];if(F){return =
F.unsubscribe(E,G);}}else{var B=3Dtrue;for(var D in =
A){if(YAHOO.lang.hasOwnProperty(A,D)){B=3DB&&A[D].unsubscribe(E,G);}}retu=
rn B;}return false;},unsubscribeAll:function(A){return =
this.unsubscribe(A);},createEvent:function(G,D){this.__yui_events=3Dthis.=
__yui_events||{};var A=3DD||{};var =
I=3Dthis.__yui_events;if(I[G]){}else{var H=3DA.scope||this;var =
E=3D(A.silent);var B=3Dnew =
YAHOO.util.CustomEvent(G,H,E,YAHOO.util.CustomEvent.FLAT);I[G]=3DB;if(A.o=
nSubscribeCallback){B.subscribeEvent.subscribe(A.onSubscribeCallback);}th=
is.__yui_subscribers=3Dthis.__yui_subscribers||{};=0A=
var F=3Dthis.__yui_subscribers[G];if(F){for(var =
C=3D0;C<F.length;++C){B.subscribe(F[C].fn,F[C].obj,F[C].override);}}}retu=
rn =
I[G];},fireEvent:function(E,D,A,C){this.__yui_events=3Dthis.__yui_events|=
|{};var G=3Dthis.__yui_events[E];if(!G){return null;}var B=3D[];for(var =
F=3D1;F<arguments.length;++F){B.push(arguments[F]);}return =
G.fire.apply(G,B);},hasEvent:function(A){if(this.__yui_events){if(this.__=
yui_events[A]){return true;}}return =
false;}};YAHOO.util.KeyListener=3Dfunction(A,F,B,C){if(!A){}else{if(!F){}=
else{if(!B){}}}if(!C){C=3DYAHOO.util.KeyListener.KEYDOWN;}var D=3Dnew =
YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=3Dnew =
YAHOO.util.CustomEvent("enabled");this.disabledEvent=3Dnew =
YAHOO.util.CustomEvent("disabled");if(typeof =
A=3D=3D"string"){A=3Ddocument.getElementById(A);}if(typeof =
B=3D=3D"function"){D.subscribe(B);}else{D.subscribe(B.fn,B.scope,B.correc=
tScope);}function =
E(J,I){if(!F.shift){F.shift=3Dfalse;}if(!F.alt){F.alt=3Dfalse;}if(!F.ctrl=
){F.ctrl=3Dfalse;}if(J.shiftKey=3D=3DF.shift&&J.altKey=3D=3DF.alt&&J.ctrl=
Key=3D=3DF.ctrl){var G;if(F.keys instanceof Array){for(var =
H=3D0;H<F.keys.length;H++){G=3DF.keys[H];if(G=3D=3DJ.charCode){D.fire(J.c=
harCode,J);break;}else{if(G=3D=3DJ.keyCode){D.fire(J.keyCode,J);break;}}}=
}else{G=3DF.keys;if(G=3D=3DJ.charCode){D.fire(J.charCode,J);}else{if(G=3D=
=3DJ.keyCode){D.fire(J.keyCode,J);}}}}}this.enable=3Dfunction(){if(!this.=
enabled){YAHOO.util.Event.addListener(A,C,E);this.enabledEvent.fire(F);}t=
his.enabled=3Dtrue;};this.disable=3Dfunction(){if(this.enabled){YAHOO.uti=
l.Event.removeListener(A,C,E);this.disabledEvent.fire(F);}this.enabled=3D=
false;};this.toString=3Dfunction(){return"KeyListener ["+F.keys+"] =
"+A.tagName+(A.id?"["+A.id+"]":"");};};YAHOO.util.KeyListener.KEYDOWN=3D"=
keydown";YAHOO.util.KeyListener.KEYUP=3D"keyup";YAHOO.util.KeyListener.KE=
Y=3D{ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35=
,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PA=
GE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:=
32,TAB:9,UP:38};YAHOO.register("event",YAHOO.util.Event,{version:"2.4.0",=
build:"733"});
------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/treeview-min.js?1209768151

/*=0A=
Copyright (c) 2007, Yahoo! Inc. All rights reserved.=0A=
Code licensed under the BSD License:=0A=
http://developer.yahoo.net/yui/license.txt=0A=
version: 2.4.0=0A=
*/=0A=
YAHOO.widget.TreeView=3Dfunction(A){if(A){this.init(A);}};YAHOO.widget.Tr=
eeView.prototype=3D{id:null,_el:null,_nodes:null,locked:false,_expandAnim=
:null,_collapseAnim:null,_animCount:0,maxAnim:2,setExpandAnim:function(A)=
{this._expandAnim=3D(YAHOO.widget.TVAnim.isValid(A))?A:null;},setCollapse=
Anim:function(A){this._collapseAnim=3D(YAHOO.widget.TVAnim.isValid(A))?A:=
null;},animateExpand:function(C,D){if(this._expandAnim&&this._animCount<t=
his.maxAnim){var A=3Dthis;var =
B=3DYAHOO.widget.TVAnim.getAnim(this._expandAnim,C,function(){A.expandCom=
plete(D);});if(B){++this._animCount;this.fireEvent("animStart",{"node":D,=
"type":"expand"});B.animate();}return true;}return =
false;},animateCollapse:function(C,D){if(this._collapseAnim&&this._animCo=
unt<this.maxAnim){var A=3Dthis;var =
B=3DYAHOO.widget.TVAnim.getAnim(this._collapseAnim,C,function(){A.collaps=
eComplete(D);});if(B){++this._animCount;this.fireEvent("animStart",{"node=
":D,"type":"collapse"});B.animate();}return true;}return =
false;},expandComplete:function(A){--this._animCount;this.fireEvent("anim=
Complete",{"node":A,"type":"expand"});},collapseComplete:function(A){--th=
is._animCount;this.fireEvent("animComplete",{"node":A,"type":"collapse"})=
;},init:function(B){this.id=3DB;if("string"!=3D=3Dtypeof =
B){this._el=3DB;this.id=3Dthis.generateId(B);}this.createEvent("animStart=
",this);this.createEvent("animComplete",this);this.createEvent("collapse"=
,this);this.createEvent("collapseComplete",this);this.createEvent("expand=
",this);this.createEvent("expandComplete",this);this._nodes=3D[];YAHOO.wi=
dget.TreeView.trees[this.id]=3Dthis;this.root=3Dnew =
YAHOO.widget.RootNode(this);var =
A=3DYAHOO.widget.LogWriter;},draw:function(){var =
A=3Dthis.root.getHtml();this.getEl().innerHTML=3DA;this.firstDraw=3Dfalse=
;},getEl:function(){if(!this._el){this._el=3Ddocument.getElementById(this=
.id);}return =
this._el;},regNode:function(A){this._nodes[A.index]=3DA;},getRoot:functio=
n(){return =
this.root;},setDynamicLoad:function(A,B){this.root.setDynamicLoad(A,B);},=
expandAll:function(){if(!this.locked){this.root.expandAll();}},collapseAl=
l:function(){if(!this.locked){this.root.collapseAll();}},getNodeByIndex:f=
unction(B){var =
A=3Dthis._nodes[B];return(A)?A:null;},getNodeByProperty:function(C,B){for=
(var A in this._nodes){var =
D=3Dthis._nodes[A];if(D.data&&B=3D=3DD.data[C]){return D;}}return =
null;},getNodesByProperty:function(D,C){var A=3D[];for(var B in =
this._nodes){var =
E=3Dthis._nodes[B];if(E.data&&C=3D=3DE.data[D]){A.push(E);}}return(A.leng=
th)?A:null;},getNodeByElement:function(C){var =
D=3DC,A,B=3D/ygtv([^\d]*)(.*)/;do{if(D&&D.id){A=3DD.id.match(B);if(A&&A[2=
]){return =
this.getNodeByIndex(A[2]);}}D=3DD.parentNode;if(!D||!D.tagName){break;}}w=
hile(D.id!=3D=3Dthis.id&&D.tagName.toLowerCase()!=3D=3D"body");return =
null;},removeNode:function(B,A){if(B.isRoot()){return false;}var =
C=3DB.parent;if(C.parent){C=3DC.parent;}this._deleteNode(B);if(A&&C&&C.ch=
ildrenRendered){C.refresh();}return =
true;},_removeChildren_animComplete:function(A){this.unsubscribe(this._re=
moveChildren_animComplete);this.removeChildren(A.node);},removeChildren:f=
unction(A){if(A.expanded){if(this._collapseAnim){this.subscribe("animComp=
lete",this._removeChildren_animComplete,this,true);YAHOO.widget.Node.prot=
otype.collapse.call(A);return =
;}A.collapse();}while(A.children.length){this._deleteNode(A.children[0]);=
}if(A.isRoot()){YAHOO.widget.Node.prototype.expand.call(A);}A.childrenRen=
dered=3Dfalse;A.dynamicLoadComplete=3Dfalse;A.updateIcon();},_deleteNode:=
function(A){this.removeChildren(A);this.popNode(A);},popNode:function(D){=
var E=3DD.parent;var B=3D[];for(var =
C=3D0,A=3DE.children.length;C<A;++C){if(E.children[C]!=3DD){B[B.length]=3D=
E.children[C];}}E.children=3DB;E.childrenRendered=3Dfalse;if(D.previousSi=
bling){D.previousSibling.nextSibling=3DD.nextSibling;}if(D.nextSibling){D=
.nextSibling.previousSibling=3DD.previousSibling;}D.parent=3Dnull;D.previ=
ousSibling=3Dnull;D.nextSibling=3Dnull;D.tree=3Dnull;delete =
this._nodes[D.index];},toString:function(){return"TreeView =
"+this.id;},generateId:function(A){var =
B=3DA.id;if(!B){B=3D"yui-tv-auto-id-"+YAHOO.widget.TreeView.counter;++YAH=
OO.widget.TreeView.counter;}return =
B;},onExpand:function(A){},onCollapse:function(A){}};YAHOO.augment(YAHOO.=
widget.TreeView,YAHOO.util.EventProvider);YAHOO.widget.TreeView.nodeCount=
=3D0;YAHOO.widget.TreeView.trees=3D[];YAHOO.widget.TreeView.counter=3D0;Y=
AHOO.widget.TreeView.getTree=3Dfunction(B){var =
A=3DYAHOO.widget.TreeView.trees[B];return(A)?A:null;};YAHOO.widget.TreeVi=
ew.getNode=3Dfunction(B,C){var =
A=3DYAHOO.widget.TreeView.getTree(B);return(A)?A.getNodeByIndex(C):null;}=
;YAHOO.widget.TreeView.addHandler=3Dfunction(B,C,A){if(B.addEventListener=
){B.addEventListener(C,A,false);}else{if(B.attachEvent){B.attachEvent("on=
"+C,A);}}};YAHOO.widget.TreeView.removeHandler=3Dfunction(B,C,A){if(B.rem=
oveEventListener){B.removeEventListener(C,A,false);}else{if(B.detachEvent=
){B.detachEvent("on"+C,A);}}};YAHOO.widget.TreeView.preload=3Dfunction(F,=
E){E=3DE||"ygtv";var =
C=3D["tn","tm","tmh","tp","tph","ln","lm","lmh","lp","lph","loading"];var=
 G=3D[];for(var A=3D1;A<C.length;A=3DA+1){G[G.length]=3D"<span =
class=3D\""+E+C[A]+"\">&#160;</span>";}var =
D=3Ddocument.createElement("div");var =
B=3DD.style;B.className=3DE+C[0];B.position=3D"absolute";B.height=3D"1px"=
;B.width=3D"1px";B.top=3D"-1000px";B.left=3D"-1000px";D.innerHTML=3DG.joi=
n("");document.body.appendChild(D);YAHOO.widget.TreeView.removeHandler(wi=
ndow,"load",YAHOO.widget.TreeView.preload);};YAHOO.widget.TreeView.addHan=
dler(window,"load",YAHOO.widget.TreeView.preload);YAHOO.widget.Node=3Dfun=
ction(C,B,A){if(C){this.init(C,B,A);}};YAHOO.widget.Node.prototype=3D{ind=
ex:0,children:null,tree:null,data:null,parent:null,depth:-1,href:null,tar=
get:"_self",expanded:false,multiExpand:true,renderHidden:false,childrenRe=
ndered:false,dynamicLoadComplete:false,previousSibling:null,nextSibling:n=
ull,_dynLoad:false,dataLoader:null,isLoading:false,hasIcon:true,iconMode:=
0,nowrap:false,_type:"Node",init:function(C,B,A){this.data=3DC;this.child=
ren=3D[];this.index=3DYAHOO.widget.TreeView.nodeCount;++YAHOO.widget.Tree=
View.nodeCount;this.expanded=3DA;this.createEvent("parentChange",this);if=
(B){B.appendChild(this);}},applyParent:function(B){if(!B){return false;=0A=
}this.tree=3DB.tree;this.parent=3DB;this.depth=3DB.depth+1;if(!this.href)=
{this.href=3D"javascript:"+this.getToggleLink();}this.tree.regNode(this);=
B.childrenRendered=3Dfalse;for(var =
C=3D0,A=3Dthis.children.length;C<A;++C){this.children[C].applyParent(this=
);}this.fireEvent("parentChange");return =
true;},appendChild:function(B){if(this.hasChildren()){var =
A=3Dthis.children[this.children.length-1];A.nextSibling=3DB;B.previousSib=
ling=3DA;}this.children[this.children.length]=3DB;B.applyParent(this);if(=
this.childrenRendered&&this.expanded){this.getChildrenEl().style.display=3D=
"";}return B;},appendTo:function(A){return =
A.appendChild(this);},insertBefore:function(A){var =
C=3DA.parent;if(C){if(this.tree){this.tree.popNode(this);}var =
B=3DA.isChildOf(C);C.children.splice(B,0,this);if(A.previousSibling){A.pr=
eviousSibling.nextSibling=3Dthis;}this.previousSibling=3DA.previousSiblin=
g;this.nextSibling=3DA;A.previousSibling=3Dthis;this.applyParent(C);}retu=
rn this;},insertAfter:function(A){var =
C=3DA.parent;if(C){if(this.tree){this.tree.popNode(this);}var =
B=3DA.isChildOf(C);if(!A.nextSibling){this.nextSibling=3Dnull;return =
this.appendTo(C);}C.children.splice(B+1,0,this);A.nextSibling.previousSib=
ling=3Dthis;this.previousSibling=3DA;this.nextSibling=3DA.nextSibling;A.n=
extSibling=3Dthis;this.applyParent(C);}return =
this;},isChildOf:function(B){if(B&&B.children){for(var =
C=3D0,A=3DB.children.length;C<A;++C){if(B.children[C]=3D=3D=3Dthis){retur=
n C;}}}return -1;},getSiblings:function(){return =
this.parent.children;},showChildren:function(){if(!this.tree.animateExpan=
d(this.getChildrenEl(),this)){if(this.hasChildren()){this.getChildrenEl()=
.style.display=3D"";}}},hideChildren:function(){if(!this.tree.animateColl=
apse(this.getChildrenEl(),this)){this.getChildrenEl().style.display=3D"no=
ne";}},getElId:function(){return"ygtv"+this.index;},getChildrenElId:funct=
ion(){return"ygtvc"+this.index;},getToggleElId:function(){return"ygtvt"+t=
his.index;},getEl:function(){return =
document.getElementById(this.getElId());},getChildrenEl:function(){return=
 =
document.getElementById(this.getChildrenElId());},getToggleEl:function(){=
return =
document.getElementById(this.getToggleElId());},getToggleLink:function(){=
return"YAHOO.widget.TreeView.getNode('"+this.tree.id+"',"+this.index+").t=
oggle()";},collapse:function(){if(!this.expanded){return ;}var =
A=3Dthis.tree.onCollapse(this);if(false=3D=3D=3DA){return =
;}A=3Dthis.tree.fireEvent("collapse",this);if(false=3D=3D=3DA){return =
;}if(!this.getEl()){this.expanded=3Dfalse;}else{this.hideChildren();this.=
expanded=3Dfalse;this.updateIcon();}A=3Dthis.tree.fireEvent("collapseComp=
lete",this);},expand:function(C){if(this.expanded&&!C){return ;}var =
A=3Dtrue;if(!C){A=3Dthis.tree.onExpand(this);if(false=3D=3D=3DA){return =
;}A=3Dthis.tree.fireEvent("expand",this);}if(false=3D=3D=3DA){return =
;}if(!this.getEl()){this.expanded=3Dtrue;return =
;}if(!this.childrenRendered){this.getChildrenEl().innerHTML=3Dthis.render=
Children();}else{}this.expanded=3Dtrue;this.updateIcon();if(this.isLoadin=
g){this.expanded=3Dfalse;return ;}if(!this.multiExpand){var =
D=3Dthis.getSiblings();for(var =
B=3D0;B<D.length;++B){if(D[B]!=3Dthis&&D[B].expanded){D[B].collapse();}}}=
this.showChildren();A=3Dthis.tree.fireEvent("expandComplete",this);},upda=
teIcon:function(){if(this.hasIcon){var =
A=3Dthis.getToggleEl();if(A){A.className=3Dthis.getStyle();}}},getStyle:f=
unction(){if(this.isLoading){return"ygtvloading";}else{var =
B=3D(this.nextSibling)?"t":"l";var =
A=3D"n";if(this.hasChildren(true)||(this.isDynamic()&&!this.getIconMode()=
)){A=3D(this.expanded)?"m":"p";}return"ygtv"+B+A;}},getHoverStyle:functio=
n(){var =
A=3Dthis.getStyle();if(this.hasChildren(true)&&!this.isLoading){A+=3D"h";=
}return A;},expandAll:function(){for(var =
A=3D0;A<this.children.length;++A){var =
B=3Dthis.children[A];if(B.isDynamic()){alert("Not supported (lazy load + =
expand all)");break;}else{if(!B.multiExpand){alert("Not supported (no =
multi-expand + expand =
all)");break;}else{B.expand();B.expandAll();}}}},collapseAll:function(){f=
or(var =
A=3D0;A<this.children.length;++A){this.children[A].collapse();this.childr=
en[A].collapseAll();}},setDynamicLoad:function(A,B){if(A){this.dataLoader=
=3DA;this._dynLoad=3Dtrue;}else{this.dataLoader=3Dnull;this._dynLoad=3Dfa=
lse;}if(B){this.iconMode=3DB;}},isRoot:function(){return(this=3D=3Dthis.t=
ree.root);},isDynamic:function(){var =
A=3D(!this.isRoot()&&(this._dynLoad||this.tree.root._dynLoad));return =
A;},getIconMode:function(){return(this.iconMode||this.tree.root.iconMode)=
;},hasChildren:function(A){return(this.children.length>0||(A&&this.isDyna=
mic()&&!this.dynamicLoadComplete));},toggle:function(){if(!this.tree.lock=
ed&&(this.hasChildren(true)||this.isDynamic())){if(this.expanded){this.co=
llapse();}else{this.expand();}}},getHtml:function(){this.childrenRendered=
=3Dfalse;var A=3D[];A[A.length]=3D"<div class=3D\"ygtvitem\" =
id=3D\""+this.getElId()+"\">";A[A.length]=3Dthis.getNodeHtml();A[A.length=
]=3Dthis.getChildrenHtml();A[A.length]=3D"</div>";return =
A.join("");},getChildrenHtml:function(){var A=3D[];A[A.length]=3D"<div =
class=3D\"ygtvchildren\"";A[A.length]=3D" =
id=3D\""+this.getChildrenElId()+"\"";if(!this.expanded||!this.hasChildren=
()){A[A.length]=3D" =
style=3D\"display:none;\"";}A[A.length]=3D">";if((this.hasChildren(true)&=
&this.expanded)||(this.renderHidden&&!this.isDynamic())){A[A.length]=3Dth=
is.renderChildren();}A[A.length]=3D"</div>";return =
A.join("");},renderChildren:function(){var =
A=3Dthis;if(this.isDynamic()&&!this.dynamicLoadComplete){this.isLoading=3D=
true;this.tree.locked=3Dtrue;if(this.dataLoader){setTimeout(function(){A.=
dataLoader(A,function(){A.loadComplete();});},10);}else{if(this.tree.root=
.dataLoader){setTimeout(function(){A.tree.root.dataLoader(A,function(){A.=
loadComplete();});},10);}else{return"Error: data loader not found or not =
specified.";}}return"";}else{return =
this.completeRender();}},completeRender:function(){var B=3D[];for(var =
A=3D0;A<this.children.length;++A){B[B.length]=3Dthis.children[A].getHtml(=
);}this.childrenRendered=3Dtrue;return =
B.join("");},loadComplete:function(){this.getChildrenEl().innerHTML=3Dthi=
s.completeRender();this.dynamicLoadComplete=3Dtrue;this.isLoading=3Dfalse=
;this.expand(true);this.tree.locked=3Dfalse;},getAncestor:function(B){if(=
B>=3Dthis.depth||B<0){return null;=0A=
}var A=3Dthis.parent;while(A.depth>B){A=3DA.parent;}return =
A;},getDepthStyle:function(A){return(this.getAncestor(A).nextSibling)?"yg=
tvdepthcell":"ygtvblankdepthcell";},getNodeHtml:function(){return"";},ref=
resh:function(){this.getChildrenEl().innerHTML=3Dthis.completeRender();if=
(this.hasIcon){var =
A=3Dthis.getToggleEl();if(A){A.className=3Dthis.getStyle();}}},toString:f=
unction(){return"Node =
("+this.index+")";}};YAHOO.augment(YAHOO.widget.Node,YAHOO.util.EventProv=
ider);YAHOO.widget.TextNode=3Dfunction(C,B,A){if(C){this.init(C,B,A);this=
.setUpLabel(C);}};YAHOO.extend(YAHOO.widget.TextNode,YAHOO.widget.Node,{l=
abelStyle:"ygtvlabel",labelElId:null,label:null,textNodeParentChange:func=
tion(){if(this.tree&&!this.tree.hasEvent("labelClick")){this.tree.createE=
vent("labelClick",this.tree);}},setUpLabel:function(A){this.textNodeParen=
tChange();this.subscribe("parentChange",this.textNodeParentChange);if(typ=
eof =
A=3D=3D"string"){A=3D{label:A};}this.label=3DA.label;this.data.label=3DA.=
label;if(A.href){this.href=3DencodeURI(A.href);}if(A.target){this.target=3D=
A.target;}if(A.style){this.labelStyle=3DA.style;}if(A.title){this.title=3D=
A.title;}this.labelElId=3D"ygtvlabelel"+this.index;},getLabelEl:function(=
){return =
document.getElementById(this.labelElId);},getNodeHtml:function(){var =
C=3D[];C[C.length]=3D"<table border=3D\"0\" cellpadding=3D\"0\" =
cellspacing=3D\"0\">";C[C.length]=3D"<tr>";for(var =
A=3D0;A<this.depth;++A){C[C.length]=3D"<td =
class=3D\""+this.getDepthStyle(A)+"\"><div =
class=3D\"ygtvspacer\"></div></td>";}var =
B=3D"YAHOO.widget.TreeView.getNode('"+this.tree.id+"',"+this.index+")";C[=
C.length]=3D"<td";C[C.length]=3D" =
id=3D\""+this.getToggleElId()+"\"";C[C.length]=3D" =
class=3D\""+this.getStyle()+"\"";if(this.hasChildren(true)){C[C.length]=3D=
" =
onmouseover=3D\"this.className=3D";C[C.length]=3DB+".getHoverStyle()\"";C=
[C.length]=3D" =
onmouseout=3D\"this.className=3D";C[C.length]=3DB+".getStyle()\"";}C[C.le=
ngth]=3D" =
onclick=3D\"javascript:"+this.getToggleLink()+"\">";C[C.length]=3D"<div =
class=3D\"ygtvspacer\">";C[C.length]=3D"</div>";C[C.length]=3D"</td>";C[C=
.length]=3D"<td ";C[C.length]=3D(this.nowrap)?" nowrap=3D\"nowrap\" =
":"";C[C.length]=3D" >";C[C.length]=3D"<a";C[C.length]=3D" =
id=3D\""+this.labelElId+"\"";if(this.title){C[C.length]=3D" =
title=3D\""+this.title+"\"";}C[C.length]=3D" =
class=3D\""+this.labelStyle+"\"";C[C.length]=3D" =
href=3D\""+this.href+"\"";C[C.length]=3D" =
target=3D\""+this.target+"\"";C[C.length]=3D" onclick=3D\"return =
"+B+".onLabelClick("+B+")\"";if(this.hasChildren(true)){C[C.length]=3D" =
onmouseover=3D\"document.getElementById('";C[C.length]=3Dthis.getToggleEl=
Id()+"').className=3D";C[C.length]=3DB+".getHoverStyle()\"";C[C.length]=3D=
" =
onmouseout=3D\"document.getElementById('";C[C.length]=3Dthis.getToggleElI=
d()+"').className=3D";C[C.length]=3DB+".getStyle()\"";}C[C.length]=3D" =
>";C[C.length]=3Dthis.label;C[C.length]=3D"</a>";C[C.length]=3D"</td>";C[=
C.length]=3D"</tr>";C[C.length]=3D"</table>";return =
C.join("");},onLabelClick:function(A){return =
A.tree.fireEvent("labelClick",A);},toString:function(){return"TextNode =
("+this.index+") =
"+this.label;}});YAHOO.widget.RootNode=3Dfunction(A){this.init(null,null,=
true);this.tree=3DA;};YAHOO.extend(YAHOO.widget.RootNode,YAHOO.widget.Nod=
e,{getNodeHtml:function(){return"";},toString:function(){return"RootNode"=
;},loadComplete:function(){this.tree.draw();},collapse:function(){},expan=
d:function(){}});YAHOO.widget.HTMLNode=3Dfunction(D,C,B,A){if(D){this.ini=
t(D,C,B);this.initContent(D,A);}};YAHOO.extend(YAHOO.widget.HTMLNode,YAHO=
O.widget.Node,{contentStyle:"ygtvhtml",contentElId:null,content:null,init=
Content:function(B,A){this.setHtml(B);this.contentElId=3D"ygtvcontentel"+=
this.index;this.hasIcon=3DA;},setHtml:function(B){this.data=3DB;this.html=
=3D(typeof B=3D=3D=3D"string")?B:B.html;var =
A=3Dthis.getContentEl();if(A){A.innerHTML=3Dthis.html;}},getContentEl:fun=
ction(){return =
document.getElementById(this.contentElId);},getNodeHtml:function(){var =
B=3D[];B[B.length]=3D"<table border=3D\"0\" cellpadding=3D\"0\" =
cellspacing=3D\"0\">";B[B.length]=3D"<tr>";for(var =
A=3D0;A<this.depth;++A){B[B.length]=3D"<td =
class=3D\""+this.getDepthStyle(A)+"\"><div =
class=3D\"ygtvspacer\"></div></td>";}if(this.hasIcon){B[B.length]=3D"<td"=
;B[B.length]=3D" id=3D\""+this.getToggleElId()+"\"";B[B.length]=3D" =
class=3D\""+this.getStyle()+"\"";B[B.length]=3D" =
onclick=3D\"javascript:"+this.getToggleLink()+"\"";if(this.hasChildren(tr=
ue)){B[B.length]=3D" =
onmouseover=3D\"this.className=3D";B[B.length]=3D"YAHOO.widget.TreeView.g=
etNode('";B[B.length]=3Dthis.tree.id+"',"+this.index+").getHoverStyle()\"=
";B[B.length]=3D" =
onmouseout=3D\"this.className=3D";B[B.length]=3D"YAHOO.widget.TreeView.ge=
tNode('";B[B.length]=3Dthis.tree.id+"',"+this.index+").getStyle()\"";}B[B=
.length]=3D"><div =
class=3D\"ygtvspacer\"></div></td>";}B[B.length]=3D"<td";B[B.length]=3D" =
id=3D\""+this.contentElId+"\"";B[B.length]=3D" =
class=3D\""+this.contentStyle+"\"";B[B.length]=3D(this.nowrap)?" =
nowrap=3D\"nowrap\" ":"";B[B.length]=3D" =
>";B[B.length]=3Dthis.html;B[B.length]=3D"</td>";B[B.length]=3D"</tr>";B[=
B.length]=3D"</table>";return =
B.join("");},toString:function(){return"HTMLNode =
("+this.index+")";}});YAHOO.widget.MenuNode=3Dfunction(C,B,A){if(C){this.=
init(C,B,A);this.setUpLabel(C);}this.multiExpand=3Dfalse;};YAHOO.extend(Y=
AHOO.widget.MenuNode,YAHOO.widget.TextNode,{toString:function(){return"Me=
nuNode ("+this.index+") =
"+this.label;}});YAHOO.widget.TVAnim=3Dfunction(){return{FADE_IN:"TVFadeI=
n",FADE_OUT:"TVFadeOut",getAnim:function(B,A,C){if(YAHOO.widget[B]){retur=
n new YAHOO.widget[B](A,C);}else{return =
null;}},isValid:function(A){return(YAHOO.widget[A]);}};}();YAHOO.widget.T=
VFadeIn=3Dfunction(A,B){this.el=3DA;this.callback=3DB;};YAHOO.widget.TVFa=
deIn.prototype=3D{animate:function(){var D=3Dthis;var =
C=3Dthis.el.style;C.opacity=3D0.1;C.filter=3D"alpha(opacity=3D10)";C.disp=
lay=3D"";var B=3D0.4;var A=3Dnew =
YAHOO.util.Anim(this.el,{opacity:{from:0.1,to:1,unit:""}},B);A.onComplete=
.subscribe(function(){D.onComplete();});A.animate();},onComplete:function=
(){this.callback();},toString:function(){return"TVFadeIn";}};YAHOO.widget=
.TVFadeOut=3Dfunction(A,B){this.el=3DA;this.callback=3DB;};YAHOO.widget.T=
VFadeOut.prototype=3D{animate:function(){var C=3Dthis;var B=3D0.4;var =
A=3Dnew =
YAHOO.util.Anim(this.el,{opacity:{from:1,to:0.1,unit:""}},B);A.onComplete=
.subscribe(function(){C.onComplete();=0A=
});A.animate();},onComplete:function(){var =
A=3Dthis.el.style;A.display=3D"none";A.filter=3D"alpha(opacity=3D100)";th=
is.callback();},toString:function(){return"TVFadeOut";}};YAHOO.register("=
treeview",YAHOO.widget.TreeView,{version:"2.4.0",build:"733"});
------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://www.buildingwebapps.com/javascripts/stars.js?1209768151

/*  Starry Widget=0A=
 *  @version 1.1 (April 27, 2007)=0A=
 *  (c) 2007 Chris Iufer <chris@duarte.com>=0A=
 *  Starry is freely distributable under the terms of an MIT-style =
license.=0A=
 *  See the Duarte Design web site: http://www.duarte.com/portfolio/=0A=
/*-----------------------------------------------------------------------=
---*/=0A=
=0A=
var debug =3D false;=0A=
=0A=
var StarryDefaults =3D {=0A=
		sprite: "/images/stars.gif",=0A=
		width: 20,=0A=
		height: 20,=0A=
		startAt: 0,=0A=
		maxLength: 5,=0A=
		multiplier: 1,=0A=
		showNull: false,=0A=
		align: 'left',=0A=
		feedback: false=0A=
};=0A=
=0A=
// The Starry Class=0A=
// new Starry('id_of_element'[, {options}]);=0A=
// This is the main starry widget. Create new widgets after window load=0A=
var Starry =3D Class.create();=0A=
Starry.prototype =3D {=0A=
	initialize: function(element) {=0A=
		this.element =3D $(element);=0A=
		this.element.className =3D "starry";				=0A=
		this.options =3D {};=0A=
		// get our defaults=0A=
		Object.extend(this.options, StarryDefaults);=0A=
		Object.extend(this.options, arguments[1] || {});		=0A=
		this.name =3D this.options.name || "starry" + id.next();=0A=
		this.element.style.height =3D this.options.height + 'px';		=0A=
		if(debug) console.log(this.options.showNull);=0A=
		// lets build our array with an extra one for null=0A=
		this.children =3D new Array(this.options.maxLength + 1);=0A=
		if(debug) console.log('children length '+ this.children.length);		=0A=
		// lets make the hidden form value=0A=
		this.hidden =3D document.createElement("input");=0A=
		this.hidden.type =3D "hidden";=0A=
		this.hidden.name =3D this.name;=0A=
		this.element.appendChild(this.hidden);				=0A=
		// build out each child=0A=
		for(i=3D0; i < this.children.length; i++) {=0A=
			this.children[i] =3D new SingleStar(this, i);=0A=
			this.element.appendChild(this.children[i].element);=0A=
		}=0A=
		if( this.options.feedback ) {=0A=
			this.feedback =3D document.createElement('div');=0A=
			this.feedback.className =3D "feedback";=0A=
			this.feedback.style.cssFloat =3D this.options.align;=0A=
			this.element.appendChild(this.feedback);=0A=
		}	=0A=
		// startup=0A=
		this.selected =3D this.options.startAt;=0A=
		this.reset(this.selected);=0A=
	},=0A=
	set: function(index) {=0A=
        	if(debug) console.log('set index '+ index);=0A=
		// set the child=0A=
		for(var i=3D1; i < this.children.length; i++)=0A=
			this.children[i].element.style.backgroundPosition =3D (i <=3D index) =
? "0 -" + this.options.height * 2 + "px" : "0 0";=0A=
		if(this.options.feedback) =0A=
			this.feedback.innerHTML =3D this.children[index].value;=0A=
 		this.selected =3D index;=0A=
		// set the form value=0A=
		this.hidden.value =3D this.children[index].value;=0A=
		if(debug) console.log('set value ' + this.hidden.value);=0A=
	},=0A=
	show: function(index) {=0A=
		if(debug) console.log('show index '+ index);		=0A=
		// show the child=0A=
		for(var i=3D1; i < this.children.length; i++)=0A=
			this.children[i].element.style.backgroundPosition =3D (i <=3D index) =
? "0 -" + this.options.height + "px" : "0 0";=0A=
		if(this.options.feedback)=0A=
			this.feedback.innerHTML =3D this.children[index].value;	=0A=
	},=0A=
	reset: function() { this.set(this.selected); },=0A=
	clear: function() {=0A=
		for(var i=3D1; i < this.children.length; i++)=0A=
			this.children[i].element.style.backgroundPosition =3D "0 0";=0A=
	}=0A=
};=0A=
=0A=
// Class: SingleStar(parent_object, index of that parent's children)=0A=
// Not to be called directly, inherits its options from a Starry object=0A=
var SingleStar =3D Class.create();=0A=
SingleStar.prototype =3D {=0A=
	initialize: function(parent, index) {=0A=
		this.parent =3D parent;=0A=
		this.index =3D index;=0A=
		if(debug) console.log('Creating star at index '+ this.index);=0A=
		this.value =3D this.index * this.parent.options.multiplier;=0A=
		if(debug) console.log('value '+ this.value);=0A=
		this.element =3D document.createElement("div");=0A=
		this.element.style.width =3D this.parent.options.width + "px";=0A=
		this.element.style.height =3D this.parent.options.height + "px";=0A=
		this.element.style.backgroundImage =3D "url(" + =
this.parent.options.sprite + ")";=0A=
		this.element.style.backgroundPosition =3D (this.index =3D=3D 0) ? "0 =
-" + this.parent.options.height * 3  +"px" : "0 0";=0A=
		this.element.className =3D "standard_star";=0A=
		this.element.style.cssFloat =3D this.parent.options.align;=0A=
		if(!this.parent.options.showNull && this.index =3D=3D 0) =
this.element.style.display =3D "none";=0A=
		this.element.onclick =3D function() { if (this.index =3D=3D 1 && =
this.parent.hidden.value =3D=3D 1) this.parent.set(0); else =
this.parent.set(this.index); }.bind(this);=0A=
		this.element.onmouseover =3D function() { =
this.parent.show(this.index); }.bind(this);=0A=
		this.element.onmouseout =3D this.parent.reset.bind(this.parent);=0A=
		if(debug) console.log('set onclick handler');=0A=
	}=0A=
};=0A=
=0A=
// this function manages an auto_increment for id's=0A=
var id =3D { start: 0, prev: 0, next: function() { return this.start + =
this.prev++; } };
------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/x-js
Content-Transfer-Encoding: quoted-printable
Content-Location: http://s7.addthis.com/js/152/addthis_widget.js

if (typeof addthis_widget15=3D=3D"undefined"){var =
addthis_widget15=3D'addthis'; var at15O=3D'http://s7.addthis.com/'; var =
at15o=3D'http://s7.addthis.com/services/'; var =
at15Y=3D'http://s7.addthis.com/select/'; var at15y=3Dnew Array( ); =
at15y['ask']=3D['Ask','ask.png']; =
at15y['delicious']=3D['Del.icio.us','delicious.png']; =
at15y['digg']=3D['Digg','digg.png']; =
at15y['email']=3D['Email','email.png']; =
at15y['favorites']=3D['Favorites','favorites.png']; =
at15y['facebook']=3D['Facebook','facebook.gif']; =
at15y['fark']=3D['Fark','fark.png']; =
at15y['furl']=3D['Furl','furl.gif']; =
at15y['google']=3D['Google','goog.png']; =
at15y['live']=3D['Live','live.gif']; =
at15y['myspace']=3D['MySpace','myspace.png']; at15y['myweb']=3D['Yahoo =
MyWeb','yahoo-myweb.png']; =
at15y['newsvine']=3D['Newsvine','newsvine.png']; =
at15y['reddit']=3D['Reddit','reddit.gif']; =
at15y['sk*rt']=3D['Sk*rt','skrt.gif']; =
at15y['slashdot']=3D['Slashdot','slashdot.png']; =
at15y['stumbleupon']=3D['StumbleUpon','su.png']; =
at15y['stylehive']=3D['Stylehive','stylehive.gif']; =
at15y['tailrank']=3D['Tailrank','tailrank2.png']; =
at15y['technorati']=3D['Technorati','technorati.png']; =
at15y['thisnext']=3D['ThisNext','thisnext.gif']; =
at15y['twitter']=3D['Twitter','twitter.gif']; =
at15y['ballhype']=3D['BallHype','ballhype.png']; =
at15y['yardbarker']=3D['Yardbarker','yardbarker.png']; =
at15y['more']=3D['More ...','more.gif']; function at15I(at15i){return =
document.getElementById(at15i); }function addthis_clearclosewin15( ){if =
(typeof at15A!=3D"undefined")clearTimeout(at15A); }function =
addthis_open(at15a,at15E,at15e,at15U){addthis_clearclosewin15( ); =
addthis_url=3Dat15e; addthis_title=3Dat15U; if (addthis_url=3D=3D'' || =
addthis_url=3D=3D'[URL]')addthis_url=3Dlocation.href; if =
(addthis_title=3D=3D'' || =
addthis_title=3D=3D'[TITLE]')addthis_title=3Ddocument.title; var =
at15u=3D020; var at15Z=3Dat15a.getElementsByTagName('img'); if (at15Z && =
at15Z[0]){at15a=3Dat15Z[0]; at15u=3D0; }atshow(at15E); var =
at15z=3Dat15X(at15a); var at15x=3Dat15z[0]+addthis_offset_left; var =
at15W=3Dat15z[1]+at15u+1+addthis_offset_top; var at15w=3Dat15V( ); var =
at15v=3Dat15T( ); var at15t=3Dat15I('addthis_dropdown15'); =
at15t.style.display=3D'block'; if =
(at15x-at15v[0]+at15t.clientWidth+024>at15w[0])at15x=3Dat15x-at15t.client=
Width; if =
(at15W-at15v[1]+at15t.clientHeight+at15a.clientHeight+024>at15w[1])at15W=3D=
at15W-at15t.clientHeight-024; at15t.style.left=3Dat15x+'px'; =
at15t.style.top=3D(at15W+at15a.clientHeight)+'px'; if =
(addthis_hide_embed){var at15S=3Dat15x+at15t.clientWidth; var =
at15s=3Dat15W+at15t.clientHeight; var =
at15R=3Ddocument.getElementsByTagName('embed'); var =
at15r=3D0,at15Q=3D0,at15q=3D0; for (at15P=3D0; at15P<at15R.length; =
at15P++){at15r=3Dat15X(at15R[at15P]); at15Q=3Dat15r[0]; =
at15q=3Dat15r[1]; if (at15x<at15Q+at15R[at15P].clientWidth && =
at15W<at15q+at15R[at15P].clientHeight){if (at15S>at15Q && =
at15s>at15q){if =
(at15R[at15P].style.visibility!=3D'hidden'){at15R[at15P].at15p=3D true; =
at15R[at15P].style.visibility=3D'hidden'; }}}}}at15N( ); return false; =
}function at15N( ){if (at15n)return; var =
at15M=3Daddthis_options.replace(/\s/g,''); var at15m=3Dat15M.split(','); =
for (var at15P=3D0; at15P<at15m.length; at15P++){var =
at15L=3Dat15m[at15P]; if (at15L in at15y){var =
at15l=3Dat15I('addthis_'+at15L+'15'); if =
(at15l)at15l.src=3Dat15o+at15y[at15L][1]; }}at15n=3D true; }function =
addthis_close( =
){at15A=3DsetTimeout("addthis_closewin15()",0764);}function =
addthis_closewin15( ){var at15t=3Dat15I('addthis_dropdown15'); =
at15t.style.display=3D'none'; var =
at15R=3Ddocument.getElementsByTagName('embed'); if =
(addthis_hide_embed){for (at15P=3D0; at15P<at15R.length; at15P++){if =
(at15R[at15P].at15p)at15R[at15P].style.visibility=3D'visible'; }}return =
false; }function addthis_sendto(at15K){if =
(at15K=3D=3D'email'){atshow(at15K); return false; }addthis_closewin15( =
); if (at15K=3D=3D'favorites'){if =
(document.all)window.external.AddFavorite(addthis_url,addthis_title); =
else window.sidebar.addPanel(addthis_title,addthis_url,''); return =
false; }if (at15K=3D=3D'stumbleupon')at15K=3D'su'; if =
(at15K=3D=3D'sk*rt')at15K=3D'skrt'; =
window.open(at15k(at15K),'addthis','scrollbars=3Dyes,menubar=3Dno,width=3D=
620,height=3D500,resizable=3Dyes,toolbar=3Dno,location=3Dno,status=3Dno')=
; return false; }function at15k(at15K){var =
at15J=3DencodeURIComponent(addthis_url); var =
at15j=3DencodeURIComponent(addthis_title); var =
at15H=3DencodeURIComponent(addthis_logo); return =
'http://www.addthis.com/bookmark.php?v=3D15&winname=3Daddthis&pub=3D'+add=
this_pub+'&s=3D'+at15K+'&url=3D'+at15J+'&title=3D'+at15j+'&logo=3D'+at15H=
+'&logobg=3D'+addthis_logo_background+'&logocolor=3D'+addthis_logo_color;=
 }function at15X(at15h){var at15G=3D0,at15g=3D0; do =
{at15G+=3Dat15h.offsetTop || 0; at15g+=3Dat15h.offsetLeft || 0; =
at15h=3Dat15h.offsetParent; }while (at15h); return [at15g,at15G]; =
}function at15V( ){var at15F=3D0; var at15f=3D0; if =
(typeof(window.innerWidth)=3D=3D'number'){at15F=3Dwindow.innerWidth; =
at15f=3Dwindow.innerHeight; }else if (document.documentElement && =
(document.documentElement.clientWidth || =
document.documentElement.clientHeight)){at15F=3Ddocument.documentElement.=
clientWidth; at15f=3Ddocument.documentElement.clientHeight; }else if =
(document.body && (document.body.clientWidth || =
document.body.clientHeight)){at15F=3Ddocument.body.clientWidth; =
at15f=3Ddocument.body.clientHeight; }return [at15F,at15f]; }function =
at15T( ){var at15D=3D0; var at15d=3D0; if =
(typeof(window.pageYOffset)=3D=3D'number'){at15d=3Dwindow.pageYOffset; =
at15D=3Dwindow.pageXOffset; }else if (document.body && =
(document.body.scrollLeft || =
document.body.scrollTop)){at15d=3Ddocument.body.scrollTop; =
at15D=3Ddocument.body.scrollLeft; }else if (document.documentElement && =
(document.documentElement.scrollLeft || =
document.documentElement.scrollTop)){at15d=3Ddocument.documentElement.scr=
ollTop; at15D=3Ddocument.documentElement.scrollLeft; }return =
[at15D,at15d]; }function at15C( ){var =
at15c=3Ddocument.createElement('link'); at15c.rel=3D'stylesheet'; =
at15c.type=3D'text/css'; at15c.href=3Daddthis_css; at15c.media=3D'all'; =
document.lastChild.firstChild.appendChild(at15c); }function at15B( =
){at15b( ); at15C( ); var at15o0=3D'<div id=3D"addthis_dropdown15" =
onmouseover=3D"addthis_clearclosewin15()" onmouseout=3D"addthis_close()" =
style=3D"z-index: 1000000; position: absolute; display: none">'; =
at15o0+=3D'<table width=3D"100%" cellpadding=3D"2" cellspacing=3D"0" =
style=3D"background-color: #EEEEEE; height: 18px">'; at15o0+=3D'<tr><td =
style=3D"font-size: 12px; color: #666666; padding-left:3px"><span =
id=3D"at_caption">Bookmark&nbsp;&amp;&nbsp;Share</span></td><td =
align=3D"right" style=3D"font-size: 9px; color: #666666; padding-right: =
3px">'+addthis_brand+'</td></tr>'; at15o0+=3D'</table>'; var at15O0=3D =
false; at15o0+=3D'<div id=3D"at_share">'; at15o0+=3D'<table =
id=3D"addthis_services" width=3D"100%" cellpadding=3D"0" =
style=3D"font-family: Verdana, Arial; font-size: 11px">'; =
at15o0+=3D'<tr><td colspan=3D"2" style=3D"height: 0px"></td></tr>'; var =
at15m=3Daddthis_options.split(','); for (var at15P=3D0; =
at15P<at15m.length; at15P++){var at15L=3Dat15m[at15P]; if (at15L in =
at15y){if (!at15O0)at15o0+=3D'<tr>'; at15o0+=3D'\x3ctd width=3D\"50%\" =
style=3D\"height: 19px\">\x3ca href=3D\"/\" onclick=3D\"return =
addthis_sendto(\''+at15L+'\');\">\x3cimg id=3D\"addthis_'+at15L+'15" =
alt=3D"" width=3D"16" height=3D"16" />&nbsp; =
'+at15y[at15L][0]+'</a></td>'; if (at15O0)at15o0+=3D'</tr>'; =
at15O0=3D!at15O0; }}if (at15O0)at15o0+=3D'<td></td></tr>'; =
at15o0+=3D'<tr><td colspan=3D"2" style=3D"height: 2px"></td></tr>'; =
at15o0+=3D'</table>'; at15o0+=3D'\x3c/div>\n'; at15o0+=3D'<div =
id=3D"at_email" style=3D"display: none; font-size: 11px; padding-left: =
20px; padding-top: 6px">'; at15o0+=3D'<table border=3D"0">'; =
at15o0+=3D'<tr><td style=3D"font-size: 12px">To:</td><td><input =
id=3D"at_to" type=3D"text" style=3D"width: 130px; height: 18px; =
font-size: 11px; font-family: Arial; color: #999999" value=3D" email =
address" onfocus=3D"checkto(this)" /></td</tr>'; at15o0+=3D'<tr><td =
style=3D"font-size: 12px">From:</td><td><input id=3D"at_from" =
type=3D"text" style=3D"width: 130px; height: 18px; font-size: 11px; =
font-family: Arial; color: #999999" value=3D" email address" =
onfocus=3D"checkto(this)"/></td</tr>'; at15o0+=3D'<tr><td =
style=3D"font-size: 12px" valign=3D"top">Note:</td><td><textarea =
id=3D"at_msg" style=3D"width: 130px; height: 36px; font-size: 11px; =
font-family: Arial;"/></textarea></td</tr>'; at15o0+=3D'<tr><td =
colspan=3D"2" align=3D"right"><span id=3D"at_success" =
style=3D"font-size: 10px; color: =
#777777;"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type=3D"button" =
value=3D"Send" onclick=3D"return addthis_send()" style=3D"font-size: =
9px"/></td</tr>'; at15o0+=3D'</table>'; at15o0+=3D'\x3c/div>\n'; =
at15o0+=3D'<table width=3D"100%" cellpadding=3D"0" cellspacing=3D"0" =
border=3D"0" style=3D"background-color: #EEEEEE">'; at15o0+=3D'<tr><td =
colspan=3D"2" align=3D"right" style=3D"padding: 0px; padding-right: =
10px; height: 11px"><img id=3D"at_img" src=3D"'+at15Y+'select_load.png" =
style=3D"width: 1px; height: 1px" /><a href=3D"http://www.addthis.com" =
target=3D"_blank" style=3D"height: 6px; padding: 0px"><img =
src=3D"'+at15o+'addthis-mini.gif" border=3D"0" style=3D"padding: 0px; =
width: 50px; height: 9px" alt=3D"" /></a></td></tr>'; =
at15o0+=3D'\x3c/table>\n'; at15o0+=3D'\x3c/div>\n'; =
at15l0=3Ddocument.createElement('div'); at15l0.innerHTML=3Dat15o0; =
document.body.insertBefore(at15l0,document.body.firstChild); =
at15l0.style.zIndex=3D03641100; }function at15b( ){at15n=3D false; if =
(typeof addthis_pub=3D=3D'undefined')addthis_pub=3D''; if (typeof =
at15i0=3D=3D'undefined')at15i0=3D'Bookmark &amp Share'; if (typeof =
addthis_brand=3D=3D'undefined')addthis_brand=3D''; if (typeof =
addthis_logo=3D=3D'undefined')addthis_logo=3D''; if (typeof =
addthis_logo_background=3D=3D'undefined')addthis_logo_background=3D''; =
if (typeof addthis_logo_color=3D=3D'undefined')addthis_logo_color=3D''; =
if (typeof =
addthis_options=3D=3D'undefined')addthis_options=3D'favorites, digg, =
delicious, google, myspace, facebook, reddit, newsvine, live, more'; if =
(typeof addthis_offset_top!=3D'number')addthis_offset_top=3D0; if =
(typeof addthis_offset_left!=3D'number')addthis_offset_left=3D0; if =
(typeof =
addthis_caption_share=3D=3D'undefined')addthis_caption_share=3D'Bookmark =
&amp; Share'; if (typeof =
addthis_caption_email=3D=3D'undefined')addthis_caption_email=3D'Email a =
Friend'; if (typeof =
addthis_css=3D=3D'undefined')addthis_css=3Dat15O+'css/152/addthis_widget.=
css'; if (typeof =
addthis_hide_embed=3D=3D'undefined')addthis_hide_embed=3D true; =
addthis_options=3Daddthis_options.replace(/\s/g,''); }function =
atshow(at15I0){var at15o1=3Dat15I('at_share'); var =
at15O1=3Dat15I('at_email'); var at15l1=3Dat15I('at_caption'); var =
at15i1=3Dat15I('at_success'); at15o1.style.display=3D'none'; =
at15O1.style.display=3D'none'; at15i1.innerHTML=3D''; if =
(at15I0=3D=3D'share' || at15I0=3D=3D''){at15o1.style.display=3D'block'; =
at15l1.innerHTML=3Daddthis_caption_share; }else =
{at15O1.style.display=3D'block'; =
at15l1.innerHTML=3Daddthis_caption_email; }}function addthis_send( ){var =
at15I1=3Dat15I('at_from'); var at15o2=3Dat15I('at_to'); var =
at15O2=3Dat15I('at_img'); var at15i1=3Dat15I('at_success'); var =
at15l2=3Dat15I('at_msg'); if (at15I1.value.indexOf('@')<0 || =
at15o2.value.indexOf('@')<0 || at15I1.value.indexOf('.')<0 || =
at15o2.value.indexOf('.')<0){alert('Please enter a valid email =
address!'); return; }at15i2=3DMath.random( ); =
at15I2=3D'http://www.addthis.com/tellfriend.php?pub=3D'+encodeURIComponen=
t(addthis_pub)+'&url=3D'+encodeURIComponent(addthis_url)+'&fromname=3Daaa=
&fromemail=3D'+encodeURIComponent(at15I1.value)+'&tofriend=3D'+encodeURIC=
omponent(at15o2.value)+'&note=3D'+encodeURIComponent(at15l2.value)+'&r=3D=
'+at15i2; at15O2.src=3Dat15I2; at15i1.innerHTML=3D'Message Sent!'; =
at15A=3DsetTimeout("addthis_closewin15()",02260); return false; =
}function checkto(at15o3){at15o3.style.color=3D'#000000'; if =
(at15o3.value=3D=3D' email address')at15o3.value=3D''; }at15B( ); }

------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://feeds.feedburner.com/~s/buildingwebappsarticles?i=http://www.buildingwebapps.com//articles/19-setting-up-rails-on-windows-xp

=0A=
if( typeof(FBSiteTrackerUri) =3D=3D "undefined" || =
typeof(FBSiteTrackerURI) =3D=3D "unknown" ) {=0A=
 var FBSiteTrackerUri =3D "buildingwebappsarticles";=0A=
 document.write('<script type=3D"text/javascript" charset=3D"utf-8" =
src=3D"http://feeds.feedburner.com/~d/static/site-tracker.js"></script>')=
;=0A=
}=0A=
    	
------=_NextPart_000_0009_01C8ADD6.55A08950
Content-Type: application/x-js
Content-Transfer-Encoding: quoted-printable
Content-Location: http://s.clicktale.net/WRa.js

var WRWarn=3D"Copyright 2006 ClickTale Ltd., US Patent =
Pending",WRA,WRD=3Ddocument,WRAU=3Dlocation,WRv,WRL,WRE=3D".clicktale.net=
/",WRAQ=3D"http://s.clicktale.net/",WRn,WRB=3Dnew =
Array(),WRw,ClickTaleCookieDomain,ClickTaleUnloadPause=3D500,ClickTaleEve=
ntsMask=3D255,ClickTaleFetchFrom,WRAh,WRAV,WRAW,WRAX,WRAY;if(typeof =
WRInitTime=3D=3D"undefined")var WRInitTime=3D(new =
Date()).getTime();if(WRD.addEventListener)WRD.addEventListener("DOMConten=
tLoaded",WRondomload,false);WRn=3DWRp();if(WRn&&WRn.substr(0,2)=3D=3D"IE"=
&&WRAU.protocol!=3D"https:"){WRD.write('<script id=3D"ClickTaleDefer" =
defer=3D"defer" =
src=3D"javascript:void(0)"><\/script>');WRD.getElementById("ClickTaleDefe=
r").onreadystatechange=3Dfunction(){if(this.readyState=3D=3D"complete")WR=
ondomload();};};WRw=3D(WRD.compatMode=3D=3D'BackCompat');WRv=3D(WRw?WRD.b=
ody:WRD.documentElement);var =
t=3DWRD.domain;if(t.search(/www\.\w+\.\w+/i)=3D=3D0)ClickTaleCookieDomain=
=3Dt.substring(4,t.length);WRo(window,"load",WRf);function =
ClickTale(Project,Prob,Dest){if(WRAh)throw"CT: Monitoring has already =
started";if(!WRn)return;if(WRAU.protocol=3D=3D"file:")return;if(!Dest)Des=
t=3D"www";WRE=3D"http://"+Dest+WRE;if(typeof =
ClickTaleSSL!=3D"undefined")if((ClickTaleSSL=3D=3D1&&WRAU.protocol=3D=3D"=
https:")||ClickTaleSSL=3D=3D2)WRAQ=3DWRE=3DWRE.replace(/^http/,'https');i=
f(ClickTaleIsPlayback())return;if(Prob=3D=3Dundefined)Prob=3D1;WRL=3DWRl(=
"WRUID");if(WRL=3D=3Dnull){if(Math.random()<Prob)WRL=3DWRAi();else =
WRL=3D0;};WRk("WRUID",WRL,365);if(WRL=3D=3D0||(WRl("WRUID")=3D=3Dnull&&Pr=
ob!=3D1))return;WRAh=3Dtrue;WRC({a:"start",t:WRI()});WRA=3DProject;var =
i=3Dnew =
Image();i.src=3DWRE+"i/"+WRA+".gif?"+WRH();i.onerror=3Dfunction(){i.onloa=
d=3Dnull;i.onerror=3Dnull;};i.onload=3Dfunction(){i.onload=3Dnull;i.onerr=
or=3Dnull;WRG(i);};};function ClickTaleIsPlayback(){return =
parent&&parent.WebPlayer;};function ClickTaleGetSID(){return typeof =
WRSID=3D=3D"number"?WRSID:null;};function ClickTaleGetUID(){var =
c=3DreadCookie("WRUID");return c>0?c:null;};function WRG(i){var =
s=3DWRD.createElement("script");s.src=3DWRAQ+"WR"+"a"+(i.width>1?"S"+i.wi=
dth:"")+"b.js";var =
dd=3DWRD.getElementById("ClickTale");if(dd)dd.appendChild(s);};function =
WRH(){return Math.floor(Math.random()*2147483647);};function =
WRAi(){return WRH()+"."+(WRInitTime&2147483647);};function =
WRI(){return(new Date()).getTime()-WRInitTime;};function =
WRC(m){if(typeof WRc=3D=3D'function')WRc(m);else =
if(WRB.push)WRB.push(m);};function =
WRf(){WRC({a:"load",w:WRs(),h:WRt(),sw:WRv.scrollWidth,sh:WRv.scrollHeigh=
t,cw:WRv.clientWidth,ch:WRv.clientHeight,t:WRI()});};function =
WRs(){return self.innerWidth||WRv.offsetWidth;};function WRt(){return =
self.innerHeight||WRv.offsetHeight;};function =
WRk(name,value,days){if(days){var date=3Dnew =
Date();date.setTime(date.getTime()+(days*86400000));var expires=3D"; =
expires=3D"+date.toGMTString();}else var =
expires=3D"";WRD.cookie=3Dname+"=3D"+value+expires+"; =
path=3D/;"+(ClickTaleCookieDomain?" =
domain=3D"+ClickTaleCookieDomain+";":"");};function WRl(name){var =
nameEQ=3Dname+"=3D";var ca=3DWRD.cookie.split(';');for(var =
i=3D0;i<ca.length;i++){var c=3Dca[i];while(c.charAt(0)=3D=3D' =
')c=3Dc.substring(1,c.length);if(c.indexOf(nameEQ)=3D=3D0)return =
c.substring(nameEQ.length,c.length);};return null;};function =
ClickTaleTag(c){WRC({a:"tag",c:c,t:WRI()});};function =
ClickTaleNote(c){WRC({a:"note",c:c,t:WRI()});};function =
ClickTaleField(f,v){WRC({a:"field",f:f,v:v,t:WRI()});};function =
ClickTaleExec(c){WRC({a:"exec",c:c,t:WRI()});};function =
ClickTaleIgnore(Days){WRk("WRUID",0,Days);};function =
ClickTaleUploadPage(Pre,Suf){if(WRAh)throw"CTUP: Monitoring has already =
started";WRAV=3Dtrue;WRAX=3DPre;WRAY=3DSuf;if(WRAW&&typeof =
WRAj=3D=3D'function')WRAj();};function =
WRondomload(){if(ClickTaleIsPlayback()||WRAW)return;var =
s=3DWRD.getElementById("ClickTaleDefer");if(s)s.parentNode.removeChild(s)=
;var reg=3Dnew RegExp("(<div =
id=3D\"?ClickTale\"?[^>]+>)\\s*<script[^>]+></script>\\s*(</div>)","i");W=
RAW=3DWRD.documentElement.innerHTML.replace(reg,"$1$2");WRC({a:"domload",=
t:WRI()});if(typeof WRAZ=3D=3D'function')WRAZ();if(WRAV&&typeof =
WRAj=3D=3D'function')WRAj();};function WRp(){var =
ua=3Dnavigator.userAgent;if(ua.indexOf("Opera =
")!=3D-1)return;if(ua.indexOf("MSIE =
6.0")!=3D-1)return"IE6";if(ua.indexOf("MSIE =
7.0")!=3D-1)return"IE7";if(ua.indexOf("Firefox/1.5")!=3D-1)return"FF15";i=
f(ua.indexOf("Firefox/2.0")!=3D-1)return"FF20";};function =
WRo(e,t,fn){if(e.addEventListener)e.addEventListener(t,fn,false);else =
if(e.attachEvent)e.attachEvent('on'+t,fn);};

------=_NextPart_000_0009_01C8ADD6.55A08950--
